sql >> Database teknologi >  >> RDS >> Sqlserver

IsNULL og Koalescerer korrekt brug

Dette er blevet hashed og gen-hashed. Ud over det tip, jeg påpegede i kommentaren og linkene og forklaringen @xQbert postet ovenfor, efter anmodning her er en forklaring af COALESCE vs. ISNULL ved hjælp af en underforespørgsel. Lad os overveje disse to forespørgsler, som med hensyn til resultater er identiske:

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

(Kommentarer om brug af TOP uden BESTIL BY til /dev/null/ tak.)

I COALESCE-sagen bliver logikken faktisk udvidet til noget som dette:

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

Med ISNULL sker dette ikke. Der er en intern optimering, der ser ud til at sikre, at underforespørgslen kun evalueres én gang. Jeg ved ikke, om nogen uden for Microsoft er fortrolige med præcis, hvordan denne optimering fungerer, men du kan dette, hvis du sammenligner planerne. Her er planen for COALESCE-versionen:

Og her er planen for ISNULL-versionen - læg mærke til hvor meget enklere det er (og at scanningen kun sker én gang):

I COALESCE-tilfældet sker scanningen to gange. Det betyder, at underforespørgslen evalueres to gange, selvom den ikke giver nogen resultater. Hvis du tilføjer en WHERE-sætning, således at underforespørgslen giver 0 rækker, vil du se lignende ulighed - planformerne kan ændre sig, men du vil stadig se en dobbeltsøgning+opslag eller scanning efter COALESCE-sagen. Her er et lidt anderledes eksempel:

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');
 

Planen for COALESCE-versionen denne gang - igen kan du se hele grenen, der repræsenterer underforespørgslen gentaget ordret:

Og igen en meget enklere plan, der udfører omtrent halvdelen af ​​arbejdet, ved hjælp af ISNULL:

Du kan også se dette spørgsmål på dba.se for mere diskussion:

Mit forslag er dette (og du kan se mine grunde til hvorfor i tippet og ovenstående spørgsmål):stol på, men bekræft. Jeg bruger altid COALESCE (fordi det er ANSI-standard, understøtter mere end to argumenter og gør ikke helt så skæve ting med datatypeprioritet) medmindre Jeg ved, at jeg bruger en underforespørgsel som et af udtrykkene (hvilket jeg ikke mindes nogensinde at have gjort uden for teoretisk arbejde som dette), eller jeg oplever et reelt problem med ydeevnen og vil bare sammenligne for at se, om COALESCE vs. ISNULL har nogen væsentlig ydelsesforskel (som jeg endnu ikke har fundet uden for underforespørgselssagen). Da jeg næsten altid bruger COALESCE med argumenter af lignende datatyper, er jeg sjældent nødt til at lave andre test end at se tilbage på, hvad jeg har sagt om det tidligere (jeg var også forfatter til aspfaq-artiklen, som xQbert påpegede , for 7 år siden).



  1. Vis ikke tomme retursæt

  2. Installation af MySQL på en VPS-server og tilslutning fra andre servere

  3. Datosammenligning giver et usædvanligt resultat - SQL Oracle

  4. Oprettelse af ENUM-variabeltype i MySQL