Улучшение производительности SQL, когда выбор выполняет вычисления - PullRequest
3 голосов
/ 15 января 2010

В приведенном ниже запросе для производительности лучше переместить оператор case в UDF? Если так, почему?

SELECT id,
       name,
       case
         when v1 = 'Y' then 'something'
         when v2 = 'K' then 'something else'
         when v3 is null then 'dont know'
         else 'default'
       end
from table

Ответы [ 4 ]

2 голосов
/ 15 января 2010

Нет, я бы оставил все как есть. Использование пользовательских функций может (в целом) иметь некоторые странные побочные эффекты и ограничения , и этот запрос просто не оправдывает их использование. Производительность UDF должна быть не лучше, чем у этого прямого запроса.

Вот соответствующая запись в блоге: http://www.bennadel.com/blog/964-SQL-User-Defined-Functions-Are-Slower-Than-Inline-Logic.htm

1 голос
/ 15 января 2010

UDF обычно работает хуже, чем оператор case в запросе. Но с большинством SQL лучше всего попробовать оба и сравнить результаты.

0 голосов
/ 15 января 2010

Кстати (извините, я не могу вспомнить, где я это читал) оптимизатор имеет шанс получить лучший план выполнения при использовании «короткой» синтаксической формы оператора case. Хотя в конечном итоге краткая форма является просто синтаксическим сахаром, она дает оптимизатору подсказку, что все сравнения основаны на простом равенстве без использования сложных выражений.

Ваше утверждение case как данное не может быть изменено, потому что вы используете 3 разных столбца, v1, v2 и v3. Но если бы вы использовали все тот же столбец, скажем, v1, то эта модификация могла бы иногда работать лучше:

SELECT
   id,
   name,
   case Coalesce(v1, 'dont know')
      when 'Y' then 'something'
      when 'K' then 'something else'
      when 'dont know' then 'dont know'
      else 'default'
   end
from table

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

Что бы это ни стоило, я полностью согласен, что UDF будет работать хуже. Практически повсеместное встраивание дает повышение производительности, поскольку позволяет избежать всей работы, необходимой для совершения вызова и возврата из вызова (если оптимизатор тайно не подставит его для вас).

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

SELECT
   id,
   name,
   coalesce(x.result, 'dont know')
from
   table t
   left join (
       select 'Y', 'something'
       union all select 'K', 'something else'
       union all select '%', 'default'
   ) x (value, result) on t.v1 like x.value

Опять же, это может быть не идеально из-за способа, которым я выбрал обработку нулей с LIKE. Тем не менее, он адекватно демонстрирует технику.

Дополнительные баллы:

  • Тестирование всегда для того, чтобы выяснить, что дает наилучшую производительность в любой ситуации. Заполните таблицу, полную 100 000 или миллион строк, и проведите несколько тестов с запущенным профилировщиком для захвата процессора, чтения, записи и продолжительности. Предпочитаю меньше процессора / чтения в течение более низкой продолжительности.

  • Хотя планы выполнения часто являются хорошими руководствами, не следует полностью доверять затратам на план выполнения, поскольку они полностью игнорируют внутренние затраты на UDF и не всегда правильно выставляют компромиссы между процессором и чтением.

  • Обычно лучше потратить немного процессора, если он избегает даже небольшого числа операций чтения. «Постоянное сканирование», которое отображается в планах выполнения для производных таблиц, как я использовал выше, всегда будет иметь незначительную стоимость. Эта стоимость намного меньше, чем почти любое количество операций чтения, связанных с доступом к диску.

0 голосов
/ 15 января 2010

Это, вероятно, не будет иметь никакого эффекта, если вы перейдете в отдельный UDF. Sql Server оптимизирует эти типы операций для повышения производительности, и ваш UDF, вероятно, все равно будет «встроен».

...