Skip to content

Настройка запросов: предикат IN

Пересказ статьи Arthur Daniels. Query tuning: The IN clause


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

CREATE NONCLUSTERED INDEX ix_DisplayName_Age on Users (DisplayName)
INCLUDE (Age)

SELECT DisplayName
FROM Users as u
WHERE Age IN (96,97,98,99,100)



Да, круто. Давайте взглянем на оператор Index Scan (сканирование индекса).



Я хочу обратить ваше внимание на нижнюю часть. Несмотря на то, что мы не использовали в этом запросе операторов OR, оптимизатор интерпретировал IN как серию OR.

Интересно, как можно оптимизировать наш запрос. Давайте иначе перепишем тот же запрос.

SELECT DisplayName
FROM Users as u
JOIN (SELECT 96 as Age UNION ALL
SELECT 97 as Age UNION ALL
SELECT 98 as Age UNION ALL
SELECT 99 as Age UNION ALL
SELECT 100 as Age ) as A1 on A1.Age = u.Age

Запрос вернет тот же самый результирующий набор. Теперь давайте запустим оба запроса в одном пакете. Проигнорировав Query Cost (стоимость запроса), просто взглянем на отличия в планах выполнения.



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

Сравнение предложения IN с UNION ALL


Имеется два значительных расхождения в планах этих запросов. Давайте посмотрим на планы выполнения, используя режим сравнения планов выполнения в Management Studio.

Если вам любопытно, выберите полное сравнение. Я объясню разницу ниже. Первый план, использующий IN, расположен слева. Второй план, использующий UNION ALL, находится справа.



Сравним выделение памяти


Ну, я люблю поговорить о выделении памяти (memory grant). Поэтому начнем отсюда.



План слева, использующий IN, не нуждается в выделении памяти.
На план справа было выделено 1Мб памяти и использовано 248Кб. Это не так плохо, но это важное различие. Если вы испытываете недостаток памяти, то можете отказаться от переписывания своего запроса, чтобы избежать выделения памяти.

Как насчет разницы в CPU?


Помним, что это тот же пример.



Итак, запрос с UNION ALL был немного быстрее. Когда мы говорим о разнице в 15 миллисекунд, я бы провел больше тестов, прежде чем принять решение. Замечу также, что оценка стоимости для этого плана была выше.

Мораль этой публикации


Мы показали, что настройка запроса может быть такой же простой, как переписывание предложения IN. Я не хочу утверждать, какой из способов лучше, поскольку это зависит от ваших условий.

Не переписывайте код, пока нет проблем с производительностью. А если вы это делаете, тщательно тестируйте.

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.