Есть масив ID Вида [123321, 154874, 12233] и тд.
Есть база в которой записаны эти ID. Как мне сделать запрос к базе, чтобы мне вернулись только те ID, которых нету в базе?
landergate: и что в того? Он фулсканом будет ходить по нему и добавлять в ответ все что не совпадает со списком id. Число проверок будет равно числу строк* числу элементов в запросе.
Евгений Безымянников: Выдача большого количества результатов займёт какое-то время в любом сценарии, независимо от того, как происходит выборка. NOT IN в этом случае на скорость не влияет. =)
landergate: в случае с in - получим записей максимум по числу элементов в запросе, в not in все кроме запроса. Разница в порядки. In - по ключу, not in - фулскан
Евгений Безымянников: На самом деле Вы правы про то, что при NOT IN MySQL решает выгрузить всю таблицу, поскольку исключённых NOT IN всё-равно будет меньше, чем остальной результат.
На практике я, впрочем, не столкнулся со значительным снижением скорости запроса, даже в том примере про 100 тысяч статей, из которых нужно скрыть 120.
Параметры взял даже больше, 150к статей и не видим 200 статей:
SELECT * FROM `160226_logs`.`picklog` WHERE `id` NOT IN (SELECT `hide_id` FROM `160331_logs`.`hide`) LIMIT 150510;
/* Affected rows: 0 Found rows: 150 510 Warnings: 0 Duration for 1 query: 0,031 sec. (+ 0,499 sec. network) */
(это не SSD и не кэш)
Так что тезис про тормоза могут быть преувеличены, надо рассматривать ситуацию на месте.
Евгений Безымянников: Типа в память часть загрузилась.
Сейчас попробую на принципиально разных таблицах, каждый раз.
Количество строк там варьируется от 8 до 15 миллионов.
select /**/ from (
select 123321 as id
union all
select 154874
union all
select 12233
) as targets
where not exists (
select 1 from tablename where tablename.id = targets.id
);