Ответ 1
Я использую запросы в формате вашего второго примера. Соединение обычно более масштабируемо, чем коррелированный подзапрос.
У меня есть 2 таблицы (A и B) с теми же первичными ключами. Я хочу выбрать все строки, которые находятся в A, а не в B. Следующие работы:
select * from A where not exists (select * from B where A.pk=B.pk);
однако это кажется довольно плохим (~ 2 секунды только на 100k строк в и на 3-10k меньше в B)
Есть ли лучший способ запустить это? Возможно, как левое соединение?
select * from A left join B on A.x=B.y where B.y is null;
По моим данным, это выглядит немного быстрее (~ 10%), но как вообще?
Я использую запросы в формате вашего второго примера. Соединение обычно более масштабируемо, чем коррелированный подзапрос.
Я думаю, что ваше последнее выражение - лучший способ. Вы также можете попробовать
SELECT A.*
from A left join B on
A.x = B.y
where B.y is null
Я также использую левые соединения с критериями типа "where table2.id is null".
Конечно, кажется более эффективным, чем опция вложенных запросов.
Объединяются, как правило, быстрее (в MySQL), но вы также должны рассмотреть свою схему индексирования, если обнаружите, что она все еще медленно движется. Как правило, любая установка поля в качестве внешнего ключа (с использованием INNODB) уже будет иметь набор индексов. Если вы используете MYISAM, убедитесь, что все столбцы в инструкции ON проиндексированы, и рассмотрите также добавление любых столбцов в предложении WHERE в конец индекса, чтобы сделать его индексом покрытия. Это позволяет движку иметь доступ ко всем данным, необходимым в индексе, устраняя необходимость возврата второго обратного пути к исходным данным. Имейте в виду, что это повлияет на скорость вложений/обновлений/удалений, но может значительно увеличить скорость запроса.
Это очень помогло мне. Joins
всегда быстрее, чем Sub Queries для получения результатов:
SELECT tbl1.id FROM tbl1 t1
LEFT OUTER JOIN tbl2 t2 ON t1.id = t2.id
WHERE t1.id>=100 AND t2.id IS NULL ;