Diferença de desempenho para COALESCE versus ISNULL?

48

Eu já vi muitas pessoas usarem a função COALESCE no lugar de ISNULL. A partir de pesquisas na Internet, descobri que o COALESCE é o padrão ANSI; portanto, há uma vantagem que sabemos o que esperar ao usá-lo. No entanto, ISNULL parece mais fácil de ler, pois parece mais claro o que está fazendo.

Também percebo que o ISNULL é meio complicado, pois age de maneira diferente em diferentes servidores de banco de dados e em diferentes idiomas.

Tudo isso, na minha opinião, se resume a estilo e padrões. Dado que o estilo é subjetivo, há alguma razão para usar o COALESCE sobre ISNULL (ou vice-versa)? Especificamente, há uma vantagem de desempenho de um sobre o outro?

Richard
fonte
11
Não vejo mencionado em nenhuma das respostas que uma subconsulta em uma COALESCE é avaliada duas vezes.
Martin Smith
4
"ISNULL parece mais fácil de ler, pois parece mais claro o que está fazendo" - sério? Acho o nome contra-intuitivo: eu esperaria que ele retornasse um booleano indicando se uma expressão foi resolvida como nula ou desconhecida. O nome COALESCEé meramente pouco intuitivo;)
onedaywhen

Respostas:

26

COALESCEé traduzido internamente para uma CASEexpressão, ISNULLé uma função interna do mecanismo.

COALESCEé uma função padrão ANSI, ISNULLé T-SQL.

As diferenças de desempenho podem surgir quando a escolha influencia o plano de execução, mas a diferença na velocidade da função bruta é minúscula .

Mark Storey-Smith
fonte
40
  • ISNULL é específico para Sybase / SQL Server
  • COALESCE é portátil

Então

  • ISNULL aceita 2 argumentos
  • COALESCE leva 1-n argumentos

Finalmente, e a parte divertida. O tipo de dados e comprimento / precisão / escala do resultado

Esse último bit é o motivo pelo qual ISNULL geralmente é usado porque é mais previsível (?) E o COALESCE pode adicionar conversões não intencionais de tipo de dados: é daí que vem o bit "mais lento"

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

Sendo todos os tipos de dados iguais, você não verá nenhuma diferença prática ...

gbn
fonte
22

Como Mark apontou, você será pressionado a encontrar diferenças de desempenho; Eu acho que outros fatores serão mais importantes. Para mim, eu sempre uso COALESCE, e a maior parte disso já foi mencionada por você ou por Mark:

  • COALESCE é o padrão ANSI. É uma coisa a menos com a qual preciso me preocupar se vou portar meu código. Para mim, pessoalmente, isso não é tão importante, porque sei com que frequência essas portas acontecem fora do mundo das salas de aula da Celko, mas para algumas pessoas isso é um benefício.
  • Ao contrário do que você disse sobre legibilidade, acho que pode ser mais difícil ler ISNULL, especialmente para usuários provenientes de outros idiomas ou plataformas em que ISNULL retorna um booleano (que não existe no SQL Server). É verdade que COALESCE é mais difícil de soletrar, mas pelo menos não leva a suposições incorretas.
  • COALESCE é muito mais flexível, como posso dizer COALESCE (a, b, c, d) enquanto que com ISNULL eu teria que fazer muitos aninhamentos para conseguir a mesma coisa.

Você também deve ter certeza de que está ciente de como a precedência do tipo de dados é tratada usando as duas funções, se você estiver usando com diferentes tipos de dados / precisões, etc.

Nota

Há uma exceção. Eles são tratados de maneira diferente nas versões atuais do SQL Server:

SELECT COALESCE((SELECT some_aggregate_query),0); 

SELECT ISNULL((SELECT some_aggregate_query),0); 

A COALESCEvariante, na verdade, será executada some_aggregate_queryduas vezes (uma vez para verificar o valor e outra para retorná-lo quando diferente de zero), enquanto ISNULLsó executará a subconsulta uma vez. Eu falo sobre algumas outras diferenças aqui:

Aaron Bertrand
fonte