alestro
@alestro

Будут ли просадки по производительности при реализации фильтров интернет магазина через sql intersect?

Имею две таблицы: товары и фильтры, которые связаны через сводную таблицу filters_products
CREATE TABLE `filters_products` (
	`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
	`filter_id` INT(11) UNSIGNED NULL DEFAULT NULL,
	`product_id` INT(11) UNSIGNED NULL DEFAULT NULL,
	`filter_value` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
	PRIMARY KEY (`id`) USING BTREE,
	UNIQUE INDEX `filter_id_product_id` (`filter_id`, `product_id`) USING BTREE,
	INDEX `FK__products` (`product_id`) USING BTREE,
	INDEX `filter_value` (`filter_value`) USING BTREE,
	CONSTRAINT `FK__filters` FOREIGN KEY (`filter_id`) REFERENCES `filters` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
	CONSTRAINT `FK__products` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB

В настоящий момент фильтр реализован через запрос вида:
SELECT * FROM products WHERE id IN (
    SELECT product_id FROM filters_products WHERE filter_id = 1 AND filter_value BETWEEN 1000 AND 4000
INTERSECT
    (SELECT product_id FROM filters_products WHERE (filter_id = 3 AND (filter_value = 'Intel® Core™ i5 11400F' OR filter_value = 'AMD Ryzen 5 5600G')))
INTERSECT 
    (SELECT product_id FROM filters_products WHERE filter_id = 2 AND filter_value = 6)
);


Насколько удачное решение, будут ли просадки по производительности при большом количестве фильтров?
  • Вопрос задан
  • 101 просмотр
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Данный фильтр - слишком избыточен. Его можно переписать через

SELECT * FROM products WHERE id IN (
    SELECT product_id FROM filters_products WHERE 
        (filter_id = 1 AND filter_value BETWEEN 1000 AND 4000)
      OR
        (filter_id = 3 AND (filter_value = 'Intel® Core™ i5 11400F' OR filter_value = 'AMD Ryzen 5 5600G'))
      OR
        (filter_id = 2 AND filter_value = 6)
);

В оригинальном запросе стоял INSERSECT и по идее надо было заменять предикаты на AND.
Но я поставил OR поскольку мне кажется что автор тоже ошибается и INSERSECT - это
слишком строгий фильтр и пересечение с ключами 1-2-3 даст пустоту. И скорее всего
там надо объединение а не пересечение.

Просадки-шмосадки... Будут или нет. Никто не знает. Смотрим execution план в двух вариантах. И сравниваем.

Еще раз я призываю всех SQL писателей - указывать целевую dbms.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы