Разница в производительности для COALESCE и ISNULL?

48

Я видел, что многие люди используют функцию COALESCE вместо ISNULL. По результатам поиска в Интернете я обнаружил, что COALESCE - это стандарт ANSI, поэтому есть преимущество в том, что мы знаем, чего ожидать при его использовании. Тем не менее, ISNULL кажется легче читать, так как кажется более ясным, что он делает.

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

Все это, на мой взгляд, сводится к стилю и стандартам. Учитывая, что стиль субъективен, есть ли причина использовать COALESCE вместо ISNULL (или наоборот)? В частности, есть ли преимущество в производительности одного над другим?

Ричард
источник
1
Я не вижу упоминания ни в одном из ответов, что подзапрос в a COALESCE оценивается дважды.
Мартин Смит
4
«ISNULL кажется легче читать, так как кажется более ясным, что он делает» - правда? Я нахожу имя встречным неинтуитивным: я ожидаю, что оно возвратит логическое значение, указывающее, было ли выражение разрешено в нуль или неизвестно. Имя COALESCEпросто не
интуитивно понятно

Ответы:

26

COALESCEвнутренне переводится в CASEвыражение, ISNULLявляется внутренней функцией двигателя.

COALESCEявляется стандартной функцией ANSI, ISNULLэто T-SQL.

Различия в производительности могут возникать и возникают, когда выбор влияет на план выполнения, но разница в скорости необработанных функций незначительна .

Марк Стори-Смит
источник
40
  • ISNULL специфичен для Sybase / SQL Server
  • КОАЛЕСС портативный

затем

  • ISNULL принять 2 аргумента
  • COALESCE принимает 1-n аргументов

Наконец, и самое интересное. Тип данных результата и длина / точность / масштаб

Этот последний бит объясняет, почему обычно используется ISNULL, потому что он более предсказуемый (?), А COALESCE может добавлять непреднамеренные преобразования типов данных: отсюда и происходит "медленный" бит

DECLARE @len10 varchar(10); --leave it NULL
SELECT
    ISNULL(@len10, '0123456789ABCDEF'),     -- gives 0123456789
    COALESCE(@len10, '0123456789ABCDEF');   -- gives 0123456789ABCDEF

Все типы данных одинаковы, вы не увидите никакой практической разницы ...

ГБН
источник
22

Как отметил Марк, вам будет сложно найти различия в производительности; Я думаю, что другие факторы будут более важными. Для меня я всегда использую COALESCE, и большая часть этого уже упоминалась вами или Марком:

  • COALESCE - это стандарт ANSI. Это еще одна вещь, о которой мне нужно беспокоиться, если я собираюсь портировать свой код. Лично для меня это не так важно, потому что я знаю, как редко такие порты бывают на самом деле за пределами классного мира Celko, но для некоторых это выгодно.
  • Вопреки тому, что вы сказали о читабельности, я считаю, что читать ISNULL может быть сложнее, особенно для пользователей, приходящих с других языков или платформ, где ISNULL возвращает логическое значение (которого нет в SQL Server). Конечно, COALESCE сложнее записать, но, по крайней мере, это не приводит к неверным предположениям.
  • COALESCE намного более гибок, как я могу сказать COALESCE (a, b, c, d), тогда как с ISNULL мне пришлось бы сделать много вложений, чтобы достичь того же самого.

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

Запись

Есть одно исключение. Они обрабатываются по-разному в текущих версиях SQL Server:

SELECT COALESCE((SELECT some_aggregate_query),0); 

SELECT ISNULL((SELECT some_aggregate_query),0); 

COALESCEВариант будет на самом деле выполнить some_aggregate_queryдважды (один раз для проверки значения, и один раз , чтобы вернуть его , когда не ноль), в то время как ISNULLтолько выполнить подзапрос один раз. Я говорю о некоторых других различиях здесь:

Аарон Бертран
источник