Рассмотрим следующие 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
Что будет работать лучше? Я предполагаю, что в целом соединение будет лучше, за исключением случаев, когда подзапрос возвращает очень маленький набор результатов.


По моим наблюдениям, сервер MSSQL выдает один и тот же план запроса для этих запросов.
Я создал простой запрос, аналогичный тем, что был в вопросе о MSSQL2005, и планы объяснения были другими. Первый запрос оказывается быстрее. Я не эксперт по SQL, но в предполагаемом плане объяснения было 37% для запроса 1 и 63% для запроса 2. Похоже, что самая большая стоимость для запроса 2 - это соединение. У обоих запросов было два просмотра таблицы.
РСУБД «переписывают» запросы, чтобы оптимизировать их, поэтому это зависит от используемой вами системы, и я предполагаю, что они в конечном итоге дают такую же производительность в большинстве «хороших» баз данных.
Предлагаю выбрать более понятный и простой в обслуживании, за свои деньги, это первый. Отладить подзапрос намного проще, поскольку его можно запускать независимо для проверки работоспособности.
Я второй ответ Тома, что вы должны выбрать тот, который легче понять и поддерживать.
План запроса любого запроса в любой базе данных невозможно предсказать, потому что вы не предоставили нам индексы или распределения данных. Единственный способ предсказать, что быстрее - запустить их в базе данных ваш.
Как правило, я обычно использую подвыборки, когда мне не нужно включать какие-либо столбцы из tblB в мое предложение select. Я бы определенно выбрал подвыборку, когда хочу использовать предикат 'in' (и обычно для 'not in', которое вы включили в вопрос) по той простой причине, что это легче понять, когда вы или кто-то еще вернулся и изменил их.
Первый запрос будет быстрее в SQL Server, что, на мой взгляд, немного интуитивно понятно - подзапросы казаться, как будто они должны быть медленнее. В некоторых случаях (по мере увеличения объемов данных) exists может быть быстрее, чем in.
некоррелированные подзапросы - это нормально. вы должны выбрать то, что описывает данные, которые вам нужны. как было отмечено, это, вероятно, будет переписано в тот же план, но не гарантируется! более того, если таблицы A и B не являются 1: 1, вы получите повторяющиеся кортежи из запроса соединения (поскольку предложение IN выполняет неявную сортировку DISTINCT), поэтому всегда лучше кодировать то, что вы хотите, и на самом деле думать о результате.
Следует отметить, что эти запросы будут давать разные результаты, если TblB.a не уникален.
Ну, это зависит от наборов данных. По моему опыту, если у вас небольшой набор данных, выберите NOT IN, если он большой, выберите LEFT JOIN. Предложение NOT IN кажется очень медленным для больших наборов данных.
Еще я мог бы добавить, что планы объяснения могут вводить в заблуждение. Я видел несколько запросов, в которых объяснение было очень высоким, а запрос выполнялся ниже 1 с. С другой стороны, я видел запросы с отличным планом объяснения, которые могли выполняться часами.
В общем, проверьте свои данные и убедитесь в этом сами.