Mysql выберите где не в таблице - PullRequest
51 голосов
/ 09 декабря 2008

У меня есть 2 таблицы (A и B) с одинаковыми первичными ключами. Я хочу выбрать все строки, которые находятся в A, а не в B. Следующие работы:

select * from A where not exists (select * from B where A.pk=B.pk);

однако это выглядит довольно плохо (~ 2 секунды только на 100 тысячах строк в A и на 3-10 тысяч меньше в B)

Есть ли лучший способ запустить это? Возможно, в качестве левого соединения?

select * from A left join B on A.x=B.y where B.y is null;

По моим данным, это, кажется, работает немного быстрее (~ 10%), но как насчет вообще?

Ответы [ 5 ]

54 голосов
/ 09 декабря 2008

Я думаю, что ваше последнее утверждение - лучший способ. Вы также можете попробовать

SELECT A.*    
from A left join B on 
    A.x = B.y
    where B.y is null
35 голосов
/ 09 декабря 2008

Я использую запросы в формате вашего второго примера. Объединение обычно более масштабируемо, чем коррелированный подзапрос.

2 голосов
/ 29 сентября 2010

Соединения, как правило, быстрее (в MySQL), но вы также должны рассмотреть свою схему индексации, если обнаружите, что она все еще движется медленно. Как правило, для любой настройки поля в качестве внешнего ключа (с использованием INNODB) уже будет установлен индекс. Если вы используете MYISAM, убедитесь, что все столбцы в операторе ON проиндексированы, и рассмотрите возможность добавления любых столбцов в предложении WHERE в конец индекса, чтобы сделать его индексом покрытия. Это позволяет механизму иметь доступ ко всем данным, необходимым в индексе, избавляя от необходимости совершать второй возврат к исходным данным. Имейте в виду, что это повлияет на скорость вставки / обновления / удаления, но может значительно увеличить скорость запроса.

2 голосов
/ 27 мая 2009

Я также использую левые соединения с критериями типа «где table2.id is null».

Конечно, кажется более эффективным, чем опция вложенного запроса.

0 голосов
/ 14 декабря 2015

Это мне очень помогло. Joins всегда быстрее, чем подзапросы, чтобы дать результаты:

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 ;
...