Влияние переменных в параметризованном SQL-запросе - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть параметризованный запрос, который выглядит следующим образом (С? Является параметром приложения):

SELECT * FROM tbl WHERE tbl_id = ?

Каковы значения производительности при добавлении переменной следующим образом:

DECLARE @id INT = ?;
SELECT * FROM tbl WHERE tbl_id = @id

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

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Если tbl_id уникально, разницы нет вообще.Я пытаюсь объяснить, почему.

SQL Server обычно может решить запрос с различными планами выполнения.SQL Server должен выбрать один.Он пытается найти наиболее эффективный без особых усилий.Как только SQL Server выбирает один план, он обычно кэширует его для последующего повторного использования.Кардинальность играет ключевую роль в эффективности плана выполнения, т. Е. Сколько строк находится на tbl с заданным значением tbl_id ?.SQL Server хранит статистику частоты значений столбцов для оценки количества элементов.

Во-первых, давайте предположим, что tbl_id не является уникальным и имеет неравномерное распределение.

В первом случае мы имеем tbl_id = ?.Давайте выясним его мощность.Первое, что нам нужно сделать, чтобы понять это, это узнать значение параметра ?.Это неизвестно?На самом деле, нет.У нас есть значение при первом выполнении запроса.SQL Server принимает это значение, переходит к хранимой статистике и оценивает cadinality для этого конкретного значения, оценивает стоимость множества возможных планов выполнения с учетом предполагаемого количества элементов, выбирает наиболее эффективный и кэширует его для последующего повторного использования.Этот подход работает большую часть времени.Однако, если вы выполните запрос позже с другим значением параметра, имеющим совершенно другую мощность, кэшированный план выполнения может оказаться очень неэффективным.

Во втором случае tbl_id = @id будет @id переменной, объявленной взапрос, это не параметр запроса.Какое значение @id ?.SQL Server рассматривает его как неизвестное значение.SQL Server достигает пиковой средней частоты из хранимой статистики как оценочное количество элементов для неизвестных значений.Затем SQL Server делает то же самое, что и раньше: он оценивает стоимость множества возможных планов выполнения с учетом предполагаемой мощности, выбирает наиболее эффективный и кэширует его для последующего повторного использования.Опять же, этот подход работает большую часть времени.Однако, если вы выполняете запрос с одним значением параметра, у которого кардинальность сильно отличается от среднего, план выполнения может быть очень неэффективным.

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

0 голосов
/ 12 сентября 2018

Одно из преимуществ второго подхода заключается в том, что оно уменьшает количество планов, которые SQL будет хранить. в первой версии он создаст другой план для каждого типа данных (tinyint, smallint, int & bigint)

это при условии, что это заявление adhoc.

Если это в сохраненном процессе - вы можете столкнуться с p-сниффингом, как упомянуто выше.

Вы можете попробовать добавить

OPTION ( OPTIMIZE FOR (@id = [some good value]))

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

...