Różnica wydajności dla COALESCE kontra ISNULL?

48

Widziałem wiele osób korzystających z funkcji COALESCE zamiast ISNULL. Z wyszukiwarek internetowych dowiedziałem się, że COALESCE jest standardem ANSI, więc mamy tę zaletę, że wiemy, czego się spodziewać podczas jego używania. Jednak ISNULL wydaje się łatwiejszy do odczytania, ponieważ wydaje się bardziej jasne, co robi.

Zdaję sobie również sprawę, że ISNULL jest dość trudny, ponieważ działa inaczej na różnych serwerach baz danych i w różnych językach.

Wszystko to, moim zdaniem, sprowadza się do stylu i standardów. Biorąc pod uwagę, że styl jest subiektywny, czy jest jakiś powód, aby używać COALESCE zamiast ISNULL (lub odwrotnie)? W szczególności, czy istnieje przewaga wydajności jednego nad drugim?

Richard
źródło
1
Nie widzę wspomnianych w żadnej z odpowiedzi, że zapytanie podrzędne w COALESCE ocenie jest oceniane dwukrotnie.
Martin Smith,
4
„ISNULL wydaje się łatwiejszy do odczytania, ponieważ wydaje się bardziej jasne, co robi” - naprawdę? Uważam, że nazwa jest sprzeczna z intuicją: spodziewałbym się, że zwróci wartość logiczną wskazującą, czy wyrażenie ma wartość zerową, czy nieznaną. Nazwa COALESCEjest po prostu nieintuicyjna;)
dniu

Odpowiedzi:

26

COALESCEjest wewnętrznie przetłumaczony na CASEwyrażenie, ISNULLjest wewnętrzną funkcją silnika.

COALESCEto standardowa funkcja ANSI, ISNULLto T-SQL.

Różnice w wydajności mogą powstać, gdy wybór wpływa na plan wykonania, ale różnica w szybkości funkcji pierwotnej jest niewielka .

Mark Storey-Smith
źródło
40
  • ISNULL jest specyficzny dla Sybase / SQL Server
  • COALESCE jest przenośny

Następnie

  • ISNULL przyjmuje 2 argumenty
  • COALESCE przyjmuje argumenty 1-n

Wreszcie i trochę zabawy. Wynikowy typ danych i długość / precyzja / skala

Ten ostatni bit jest zwykle używany ISNULL, ponieważ jest bardziej przewidywalny (?), A COALESCE może dodawać niezamierzone konwersje typów danych: stąd pochodzi bit „jest wolniejszy”

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

Wszystkie typy danych są takie same, nie zobaczysz żadnej praktycznej różnicy ...

gbn
źródło
22

Jak zauważył Mark, ciężko będzie znaleźć różnice w wydajności; Myślę, że inne czynniki będą ważniejsze. Dla mnie zawsze używam COALESCE, a większość z nich została już wspomniana przez Ciebie lub Marka:

  • COALESCE jest standardem ANSI. To jedna mniejsza rzecz, o którą muszę się martwić, jeśli zamierzam przenieść swój kod. Dla mnie osobiście nie jest to tak ważne, ponieważ wiem, jak często takie porty zdarzają się poza światem klasy Celko, ale dla niektórych osób jest to korzyść.
  • W przeciwieństwie do tego, co powiedziałeś o czytelności, uważam, że trudniej jest odczytać ISNULL, szczególnie dla użytkowników pochodzących z innych języków lub platform, na których ISNULL zwraca wartość logiczną (która nie istnieje w SQL Server). To prawda, że ​​COALESCE trudniej jest przeliterować, ale przynajmniej nie prowadzi to do błędnych założeń.
  • COALESCE jest o wiele bardziej elastyczny, jak mogę powiedzieć COALESCE (a, b, c, d), podczas gdy z ISNULL musiałbym dużo zagnieżdżać, aby osiągnąć to samo.

Należy również upewnić się, że użytkownik jest świadomy sposobu, w jaki pierwszeństwo typu danych jest obsługiwane przy użyciu dwóch funkcji, jeśli jest używany z różnymi typami danych / dokładnościami itp.

Uwaga

Jest jeden wyjątek. Są obsługiwane inaczej w bieżących wersjach SQL Server:

SELECT COALESCE((SELECT some_aggregate_query),0); 

SELECT ISNULL((SELECT some_aggregate_query),0); 

COALESCEWariant będzie faktycznie wykonać some_aggregate_querydwa razy (raz, aby sprawdzić wartość, a raz wrócić, gdy non-zero), podczas gdy ISNULLwykona tylko raz podzapytania. Mówię tutaj o kilku innych różnicach:

Aaron Bertrand
źródło