2010-01-14 4 views
93

Мне любопытно, какое из следующих ниже было бы более эффективным?
Я всегда был немного осторожен в использовании IN, потому что я считаю, что SQL Server превращает результирующий набор в большой оператор IF. Для большого набора результатов это может привести к низкой производительности. Для небольших наборов результатов я не уверен, что это предпочтительнее. Для больших результирующих наборов не будет более эффективным EXISTS?SQL Server IN против EXISTS Производительность

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2) 

против

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2]) 
+6

Лучший способ выяснить это попробовать и сделать некоторые meassurements. –

+10

там ** получил **, чтобы быть gazillion дубликаты для этого ...... –

+0

@marc_s: да, но я думаю, что это действительно зависит от случая. На мой взгляд, канонический ответ - это клаусбыковский (или тот, кто может претендовать на уровень техники). – RedFilter

ответ

117

EXISTS будет быстрее, потому что, как только двигатель нашел удар, он перестал глядя, как условие оказалось правда.
С IN он будет собирать все результаты по подзапросу перед дальнейшей обработкой.

+3

Это хороший момент. Инструкция IN требует, чтобы SQL Server генерировал полный набор результатов, а затем создавал большой оператор IF, который я думаю. –

+63

Это было правдой, но в текущих версиях (по крайней мере, в 2008 году) оптимизатор намного умнее ... на самом деле он рассматривает IN() так же, как EXISTS(). –

+10

@ Аарон - да, как правило, оптимизатор будет внутренне производить лучший план. Однако, полагаясь на внутренние ярлыки, может быть вредно в более сложных сценариях. –

-1

Off верхней части моей головы, а не гарантированно правильно: я считаю, что второй будет быстрее в этом случае.

  1. В первом случае коррелированный подзапрос, скорее всего, вызовет запуск подзапроса для каждой строки.
  2. Во втором примере подзапрос должен выполняться только один раз, поскольку не коррелирован.
  3. Во втором примере IN будет замыкаться на короткое замыкание, как только он найдет совпадение.
3

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

33

Я провел некоторое тестирование на SQL Server 2005 и 2008, а на обоих EXISTS и IN вернулся с тем же самым фактическим планом выполнения, как и другие. Оптимизатор является оптимальным. :)

Что-то, чтобы быть в курсе, хотя, EXISTS, IN, и JOIN может иногда возвращать разные результаты, если вы не фраза вашего запроса впору: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

1

Для оптимизации EXISTS, очень буквальные; что-то просто должно быть там, но на самом деле вам не нужны какие-либо данные, возвращенные из коррелированного подзапроса. Вы просто оцениваете логическое состояние.

Итак:

WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

Поскольку коррелированный суб-запрос RBAR, первый результат хит делает условие истинно, и он не обрабатывается дальше.

+0

Я всегда был очень осторожен в использовании кодирования LEFT JOIN + NULL, потому что очень легко получить пропущенные или искаженные результаты, если вы не очень осторожны в обработке NULL. Я очень редко обнаружил ситуацию, когда EXISTS или CTE (для поиска дублирования или синтетической вставки для отсутствующих данных) не отвечают одинаковым требованиям и превосходят LEFT JOIN + NULL –

+2

. TOP 1 должен быть полным посторонним (или избыточность события) при использовании с EXISTS. EXISTS всегда возвращает, как только найдет соответствующую строку. –

+0

Пока я не видел каких-либо преимуществ в области производительности при таком подходе. Пожалуйста, покажите несколько скриншотов планов выполнения. – montewhizdoh

28

Принятый ответ близоруким и вопрос немного свободно в том, что:

1) Ни в явном виде не упоминается, присутствует ли индекс покрытия в слева, справа или с обеих сторон.

2) Не учитывается размер ввода левого бокового набора и вход с правой стороны.
(Вопрос просто упоминает общий большой результат комплект).

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

Обе формы могут быть преобразованы в формы объединений внутри, имеют порядок обращения в обратном порядке и выполняются как цикл, хеш или слияние - на основе оцененных строк строк (слева и справа) и существования индекса в левом, правом или обе стороны.

+2

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