У меня есть запрос к большой таблице, которая выглядит так:
declare @myIdParam int = 1
select *
from myTable
where (@myIdParam is null or myTable.Id = @myIdParam)
В предложении where есть несколько подобных условных выражений, подобных этому, и есть также много объединений, но это краткое изложение.
Фактически, если @myIdParam имеет значение null, мы не хотим ограничивать результаты с помощью этого параметра.
Я не специалист по БД, но из моих тестов кажется, что эта проверка NULL выполняется для каждой записи и никак не оптимизирована.
Если я уберу проверку «ноль» и предположу, что параметр не равен нулю, запрос мгновенно возвращается. В противном случае это займет до десяти секунд.
Есть ли способ оптимизировать это, чтобы проверка выполнялась только один раз во время выполнения?
sql-server
null
Mystagogue
источник
источник
OPTION(RECOMPILE)
Ответы:
Одним из способов является использование динамического SQL с использованием нулевой проверки для необязательного добавления этой части предложения where.
источник
sp_ExecuteSQL
отсутствует, и@vc_dynamicsql
параметр должен быть aNVARCHAR
.Каждый раз, когда вы помещаете функцию вокруг столбца ISNULL (@var, table.col), например, вы удаляете возможность SQL использовать индекс. Это действительно лучший вариант, если вы хотите сохранить его в одном запросе.
В противном случае у вас есть два варианта. Первый - это динамический SQL, и для этого достаточно ответа @ Mystagogue, в противном случае вы можете задать два запроса, например:
И в этом формате, и в динамическом SQL вы фактически получите различный план запросов для каждого из запросов (который потенциально даст лучшую производительность).
источник
Ну, вы можете:
Имейте в виду, однако, что
nullif()
функция по сути является оберткойcase
. Это не серебряная пуля, которая волшебным образом устраняетOR
и, следовательно, ускоряет запрос.источник
UNION
s. Когда у меня была именно эта задача, я выбрал динамический SQL.