Вопрос

Мне любопытно, что из приведенного ниже было бы более эффективным?

Я всегда был немного осторожен в использовании IN потому что я считаю, что SQL Server превращает результирующий набор в большой IF заявление.Для большого результирующего набора это может привести к снижению производительности.Для небольших наборов результатов я не уверен, что ни то, ни другое предпочтительнее.Для больших наборов результатов не было бы 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])
Это было полезно?

Решение

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

С IN, он соберет все результаты подзапроса перед дальнейшей обработкой.

Другие советы

Общепринятый ответ недальновиден, и вопрос в этом смысле немного размыт:

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

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

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

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

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

Тем не менее, что-то, о чем следует знать, СУЩЕСТВУЕТ, и JOIN иногда может возвращать разные результаты, если вы неправильно сформулируете свой запрос: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

Я бы выбрал EXISTS OVER IN, смотрите ссылку ниже:

SQL Сервер:ПРИСОЕДИНИТЬСЯ К vs В vs СУЩЕСТВУЕТ - логическая разница

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

Таким образом, IN - это не то же самое, что EXISTS, и он не создаст тот же план выполнения.

Обычно EXISTS используется в коррелированном подзапросе, это означает, что вы СОЕДИНИТЕ внутренний запрос EXISTS со своим внешним запросом.Это добавит больше шагов для получения результата, поскольку вам нужно решить соединения внешнего запроса, а соединения внутреннего запроса затем сопоставляют свои предложения where, чтобы объединить оба.

Обычно IN используется без соотнесения внутреннего запроса с внешним запросом, и это может быть решено всего за один шаг (в лучшем случае).

Подумайте об этом:

  1. Если вы используете IN и результатом внутреннего запроса являются миллионы строк с различными значениями, он, вероятно, будет выполняться МЕДЛЕННЕЕ, чем EXISTS, учитывая, что запрос EXISTS является производительным (имеет правильные индексы для объединения с внешним запросом).

  2. Если вы используете EXISTS и соединение с вашим внешним запросом является сложным (выполнение занимает больше времени, подходящих индексов нет), это замедлит выполнение запроса на количество строк во внешней таблице, иногда расчетное время завершения может исчисляться днями.Если количество строк приемлемо для вашего данного оборудования или количество элементов данных правильное (например, меньшее количество различных значений в большом наборе данных) IN может работать быстрее, чем СУЩЕСТВУЕТ.

  3. Все вышесказанное будет учтено, когда у вас будет достаточное количество строк в каждой таблице (под справедливым я подразумеваю то, что превышает пороговые значения вашего процессора и / или оперативной памяти для кэширования).

Итак, ОТВЕТ ТАКОВ: это ЗАВИСИТ.Вы можете написать сложный запрос внутри IN или EXISTS , но, как правило, вы должны пытаться использовать IN с ограниченным набором различных значений и EXISTS, когда у вас много строк с большим количеством различных значений.

Хитрость заключается в том, чтобы ограничить количество сканируемых строк.

С уважением,

МарианоК

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

Итак:

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

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

Здесь есть много вводящих в заблуждение ответов, в том числе высоко оцененный (хотя я не верю, что их действия имели в виду вред). Короткий ответ таков:Это одно и то же.

В языке (T-) SQL есть много ключевых слов, но, в конце концов, единственное, что действительно происходит на оборудовании, - это операции, указанные в плане выполнения запроса.

Реляционная (математическая теория) операция, которую мы выполняем, когда вызываем [NOT] IN и [NOT] EXISTS является полусоединением (anti-join при использовании NOT).Не случайно, что соответствующие операции sql-сервера имеют с тем же именем.Нет никакой операции, в которой упоминалось бы IN или EXISTS соединения только в любом месте (анти-) полусоединения.Таким образом, не существует никакого способа, чтобы логически эквивалентный IN против EXISTS выбор может повлиять на производительность, потому что есть один-единственный способ получить их результаты - операция выполнения (анти) полусоединения.

Пример:

Запрос 1 ( план )

select * from dt where dt.customer in (select c.code from customer c where c.active=0)

Запрос 2 ( план )

select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)

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

  1. В первом случае коррелированный подзапрос, скорее всего, приведет к выполнению подзапроса для каждой строки.
  2. Во втором примере подзапрос должен выполняться только один раз, поскольку не коррелирован.
  3. Во втором примере IN произойдет короткое замыкание, как только он найдет совпадение.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top