Как оптимизировать NOT IN (SELECT)?

Пользователь по сложному условию ищет, например, товары. Каждый раз нужно выводить товар, которые он еще не видел. Для этого ведется таблица, в которой записываются, какие товары уже были показаны. Получается примерно такой запрос.
SELECT `item_id`, ... FROM `items_table` AS t1
WHERE [сложное условие для поиска] 
AND t1.`item_id` NOT IN 
( SELECT t2.`shown_id` FROM `shown_table` AS t2 WHERE t2.`user_id`=$user_id ) 
LIMIT 1;

После показа добавляем запись о просмотре
INSERT INTO `shown_table` ( `user_id`, `shown_id` ) VALUES ( $user_id, $shown_id );

Задумался о проверке условия NOT IN. Если просмотренных товаров будет много, то надо будет пробегать и проверять большой набор чисел. Можно ли как-то создать временные индексы для результатов промежуточного SELECT или MySQL сама все это оптимизирует?
  • Вопрос задан
  • 304 просмотра
Решения вопроса 1
@Q_BASIC
Программист
Это может тормозить, если записей в таблице shown_table у одного пользователя будут десятки или сотни тысяч строк. Чтобы такого не было, удаляй старые, например. А вообще вряд ли столько накопится.

Индексы тут только усугубят ситуацию, потому что это не серебряная пуля, у них есть плюсы и минусы свои. Лишние индексы раздувают размер таблицы и тормозят вставку/обновление.

Вам хватит индекса на shown_table.user_id и items_table.item_id
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Revencu
@Revencu
SELECT `item_id`, ... 
FROM `items_table` AS t1
LEFT JOIN `shown_table` AS t2 on t1.`item_id`=t2.`shown_id`
WHERE [сложное условие для поиска] 
AND  t2.`user_id`=$user_id AND t2.`item_id` IS NULL
LIMIT 1;
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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