Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

IsNULL и правилното използване на Coalesce

Това е хеширано и повторно хеширано. В допълнение към съветът, който посочих в коментара и връзките и обяснението @xQbert, публикувано по-горе, по заявка тук е обяснение на COALESCE срещу ISNULL с помощта на подзаявка. Нека разгледаме тези две заявки, които по отношение на резултатите са идентични:

SELECT COALESCE((SELECT TOP (1) name FROM sys.objects), N'foo');

SELECT ISNULL((SELECT TOP (1) name FROM sys.objects), N'foo');

(Коментари относно използването на TOP без ORDER BY към /dev/null/ благодаря.)

В случая COALESCE логиката всъщност се разширява до нещо подобно:

SELECT CASE WHEN (SELECT TOP (1) ...) IS NULL
    THEN (SELECT TOP (1) ...)
    ELSE N'foo'
END

С ISNULL това не се случва. Има вътрешна оптимизация, която изглежда гарантира, че подзаявката се оценява само веднъж. Не знам дали някой извън Microsoft е запознат с това как точно работи тази оптимизация, но можете да го направите, ако сравните плановете. Ето плана за версията COALESCE:

И ето плана за ISNULL версията - забележете колко по-опростен е (и че сканирането се случва само веднъж):

В случая COALESCE сканирането се извършва два пъти. Това означава, че подзаявката се оценява два пъти, дори и да не дава никакви резултати. Ако добавите клауза WHERE, така че подзаявката да дава 0 реда, ще видите подобно несъответствие - формите на плана може да се променят, но пак ще видите двойно търсене+търсене или сканиране за случая COALESCE. Ето един малко по-различен пример:

SELECT COALESCE((SELECT TOP (1) name FROM sys.objects 
    WHERE name = N'no way this exists'), N'foo');

SELECT ISNULL((SELECT TOP (1) name FROM sys.objects 
    WHERE name = N'no way this exists'), N'foo');

Планът за версията COALESCE този път - отново можете да видите целия клон, който представлява подзаявката, повторена дословно:

И отново много по-опростен план, който върши приблизително половината работа, използвайки ISNULL:

Можете също да видите този въпрос на dba.se за още дискусия:

Моето предложение е следното (и можете да видите причините защо в съвета и горния въпрос):доверявайте се, но проверявайте. Винаги използвам COALESCE (защото е стандарт ANSI, поддържа повече от два аргумента и не прави толкова странни неща с приоритет на типа данни) освен ако Знам, че използвам подзаявка като един от изразите (което не си спомням да съм правил извън теоретична работа като тази) или изпитвам реален проблем с производителността и просто искам да сравня, за да видя дали COALESCE срещу ISNULL има някакви значителна разлика в производителността (която извън случая на подзаявка, все още трябва да открия). Тъй като почти винаги използвам COALESCE с аргументи от подобни типове данни, рядко ми се налага да правя каквото и да е тестване, освен да поглеждам назад към това, което съм казал за него в миналото (също така бях автор на статията за aspfaq, която xQbert посочи , преди 7 години).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server:NEWID() винаги ли дава уникален идентификатор?

  2. SQL Server 2005 - Ред на вътрешните съединения

  3. SQL. SP или функцията трябва да изчисли следващата дата за петък

  4. Изберете размер на базата данни на SQL Server

  5. SQL сървър (MSSQL DBA) Уроци за база данни за начинаещи администратори на бази данни