Как упоминает @ GordonLinoff , ваш лучший вариант - изучить используемые индексы.Он также намного лучше, чем я;так что прими его совет над моим, если сможешь.Однако, если по какой-то причине в вашей компании не разрешен динамический SQL или перезапись не возможна, читайте дальше ...
Возможно, у вас не такая большая проблема, как вы думаете;видели ли вы проблему с производительностью, или вы просто смотрите на код и думаете, что «много вещей происходит с большим количеством скобок, так что это плохо»?
то есть, взять эту строку: (@IdSenales IS NULL OR senalesIds.id = comp.IdSenal)
,При этом параметр сравнивается с нулевым значением, поэтому его нужно оценивать только один раз, а не один раз на строку;что не так уж плохо.После этого ничем не отличается от того, что у вас нет этого утверждения или только senalesIds.id = comp.IdSenal
.То же самое верно для большинства этих строк.
Тем не менее, SQL сгенерирует план запроса при первом запуске этого кода и впоследствии будет использовать его для всех последующих запросов, независимо от того, какие параметры были использованы;поэтому план может быть совершенно неуместным для нового набора опций.Хорошим решением здесь является добавление OPTION (RECOMPILE)
.Вы найдете хорошее объяснение этому здесь: https://blogs.msdn.microsoft.com/robinlester/2016/08/10/improving-query-performance-with-option-recompile-constant-folding-and-avoiding-parameter-sniffing-issues/
Помимо этого, эта строка может быть проблемой, так как она включает применение функции, выход которой будет различным для каждой строки;так что будет нелегко оптимизировать:
(emision.Fecha BETWEEN @FechaDesdeContrato AND ISNULL(@FechaHastaContrato, emision.fecha))
Измените это на:
(emision.Fecha >= @FechaDesdeContrato AND (emision.Fecha <= @FechaHastaContrato ))
... и вы должны быть в порядке.
Полный код:
WHERE
(@IdSenales IS NULL OR senalesIds.id = comp.IdSenal)
AND
(@IdAnunciantes IS NULL OR anunciantesIds.id = comp.IdAnunciante)
AND
(@IdProgramas IS NULL OR programasIds.id = emision.IdProgramaVariante)
AND
(@IdTipoPublicidades IS NULL OR publicidadesIds.id = orden.IdTipoPublicidad)
AND
(@Canje = 0 OR (@canje = 1 AND comp.IdTipoCondicionCobro != 12))
AND
(emision.Fecha >= @FechaDesdeContrato AND (@FechaHastaContrato is null or emision.Fecha <= @FechaHastaContrato ))
AND
(comp.FechaEmision BETWEEN @FechaDesde AND @FechaHasta)
AND
(@IdSectorImputacion = 0 OR @IdSectorImputacion = simp.IdSectorImputacion)
OPTION (RECOMPILE)