Отбор против внешнего соединения - PullRequest
8 голосов
/ 06 сентября 2008

Рассмотрим следующие 2 запроса:

select tblA.a,tblA.b,tblA.c,tblA.d
from tblA
where tblA.a not in (select tblB.a from tblB)

select tblA.a,tblA.b,tblA.c,tblA.d
from tblA left outer join tblB
on tblA.a = tblB.a where tblB.a is null

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

Ответы [ 8 ]

16 голосов
/ 06 сентября 2008

СУБД «переписывают» запросы, чтобы оптимизировать их, поэтому это зависит от используемой вами системы, и я думаю, что в конечном итоге они дают одинаковую производительность в большинстве «хороших» баз данных.

Я предлагаю выбрать тот, который яснее и проще в обслуживании, за мои деньги, это первый. Гораздо проще отладить подзапрос, так как он может быть запущен независимо для проверки работоспособности.

4 голосов
/ 15 сентября 2008

некоррелированные подзапросы в порядке. Вы должны идти с тем, что описывает данные, которые вы хотите. как уже отмечалось, это, вероятно, переписывается в тот же план, но не гарантировано! Более того, если таблицы A и B не равны 1: 1, вы получите дубликаты кортежей из запроса соединения (так как предложение IN выполняет неявную сортировку DISTINCT), поэтому всегда лучше кодировать то, что вы хотите, и на самом деле думать о результате.

3 голосов
/ 16 сентября 2008

Ну, это зависит от наборов данных. Исходя из моего опыта, если у вас есть небольшой набор данных, тогда выберите NOT IN, если он большой, перейдите к левому соединению. Предложение NOT IN в больших наборах данных выглядит очень медленно.

Еще одна вещь, которую я могу добавить, это то, что планы объяснения могут вводить в заблуждение. Я видел несколько запросов, где объяснение было очень высоким, и запрос выполнялся под 1 с. С другой стороны, я видел запросы с отличным планом объяснения, и они могли работать часами.

Так что, в общем, проверьте свои данные и убедитесь сами.

2 голосов
/ 07 сентября 2008

Я второй ответ Тома, что вы должны выбрать тот, который легче понять и поддерживать.

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

Как правило, я склонен использовать подвыборы, когда мне не нужно включать какие-либо столбцы из tblB в мое предложение select. Я определенно выбрал бы дополнительный выбор, когда я хочу использовать предикат «in» (и обычно «не в», который вы включили в вопрос), по той простой причине, что их легче понять, когда вы или кто-то еще вернулся и изменил их.

1 голос
/ 15 сентября 2008

Следует отметить, что эти запросы будут давать разные результаты, если TblB.a не будет уникальным.

1 голос
/ 12 сентября 2008

Первый запрос будет быстрее в SQL Server, который, на мой взгляд, немного противоречит интуиции - подзапросы кажутся такими, как будто они должны быть медленнее. В некоторых случаях (при увеличении объемов данных) exists может быть быстрее, чем in.

0 голосов
/ 06 сентября 2008

Я создал простой запрос, аналогичный приведенному в вопросе на MSSQL2005, и планы объяснения были другими. Первый запрос выглядит быстрее. Я не эксперт по SQL, но предполагаемый план объяснения содержал 37% для запроса 1 и 63% для запроса 2. Похоже, что самая большая стоимость запроса 2 - это объединение. Оба запроса имели два сканирования таблицы.

0 голосов
/ 06 сентября 2008

По моим наблюдениям, MSSQL-сервер вырабатывает один и тот же план запросов для этих запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...