Оптимизация оператора предложения T-SQL Where (дополнительные параметры для StoredProc) - PullRequest
16 голосов
/ 08 октября 2009

Я уже давно борюсь с этим. У меня есть сохраненный процесс, который принимает 3 параметра, которые используются для фильтрации. Если определенное значение передается, я хочу фильтровать по этому. Если передано -1, дай мне все.

Я пробовал это двумя способами:

Первый способ:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
parm1 = CASE WHEN @PARM1= -1 THEN parm1  ELSE @PARM1 END  
AND parm2 = CASE WHEN @PARM2 = -1 THEN parm2  ELSE @PARM2 END  
AND parm3 = CASE WHEN @PARM3 = -1 THEN parm3  ELSE @PARM3 END

Второй способ:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
(@PARM1 = -1 OR parm1 = @PARM1)  
AND (@PARM2 = -1 OR parm2 = @PARM2)  
AND (@PARM3 = -1 OR parm3 = @PARM3)  

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

Основная таблица, из которой выбирается это представление, содержит где-то около 1,5 миллиона записей, и представление продолжает объединяться примерно с 15 другими таблицами, чтобы собрать кучу другой информации.

Оба эти метода медленные ... отводят меня от мгновенного до где-то от 2-40 секунд, что в моей ситуации совершенно неприемлемо.

Есть ли лучший способ, который не предусматривает разбиение его на каждый отдельный случай конкретного против -1?

Любая помощь приветствуется. Спасибо.

Ответы [ 5 ]

6 голосов
/ 08 октября 2009

Я где-то читал, что второй путь будет коротким замыканием и никогда не оценивать вторую часть, если это правда. Мой администратор БД сказал, что это вызывает сканирование таблицы.

Вы прочитали неправильно; это будет не короткое замыкание. Ваш DBA прав; он не будет хорошо работать с оптимизатором запросов и, скорее всего, вызовет сканирование таблицы.

Первый вариант почти так же хорош, как и получается. Вы можете улучшить динамический SQL или длинную хранимую процедуру со всеми возможными комбинациями столбцов фильтра, чтобы получить независимые планы запросов. Вы также можете попробовать использовать опцию «WITH RECOMPILE», но я не думаю, что она вам поможет.

5 голосов
/ 08 октября 2009

если вы используете SQL Server 2005 или выше, вы можете использовать IF для создания нескольких версий запроса с правильным WHERE, чтобы можно было использовать индекс. Каждый план запроса будет помещен в кеш запроса.

также, вот очень полная статья на эту тему:

Условия динамического поиска в T-SQL Эрланда Соммарского

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

вот оглавление:

  Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History
2 голосов
/ 08 октября 2009

Если вы передаете нулевое значение, когда хотите всего, тогда вы можете написать свое предложение where как

   Where colName = IsNull(@Paramater, ColName)  

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

Единственный подход к ускорению - добавить индекс для столбца, к которому производится фильтрация, в предложении Where. Уже есть? Если нет, то это приведет к значительному улучшению.

0 голосов
/ 03 марта 2011

SQL 2008 и более поздние версии вносят некоторые улучшения в оптимизацию для таких вещей, как (MyCase IS NULL OR MyCase = @MyCaseParameter) AND ....

Если вы можете обновить и добавить OPTION (RECOMPILE), чтобы получить приличное совершенство для всех возможных комбинаций параметров (это ситуация, когда не существует единого плана, подходящего для всех возможных комбинаций параметров), вы можете обнаружить, что это хорошо работает.

http://blogs.msdn.com/b/bartd/archive/2009/05/03/sometimes-the-simplest-solution-isn-t-the-best-solution-the-all-in-one-search-query.aspx

0 голосов
/ 08 октября 2009

Я не могу думать иначе, чем делать:

ГДЕ

(MyCase IS NULL ИЛИ MyCase = @MyCaseParameter) И ....

Второй вариант более прост и удобен для чтения, если вы спросите меня.

...