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

IsNULL e Coalesce un uso corretto

Questo è stato sottoposto a hash e rehashing. Oltre a il suggerimento che ho indicato nel commento e i collegamenti e la spiegazione @xQbert pubblicati sopra, su richiesta ecco una spiegazione di COALESCE vs. ISNULL utilizzando una sottoquery. Consideriamo queste due query, che in termini di risultati sono identiche:

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

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

(Commenti sull'utilizzo di TOP senza ORDER BY a /dev/null/ grazie.)

Nel caso COALESCE, la logica viene effettivamente estesa a qualcosa del genere:

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

Con ISNULL, questo non accade. Esiste un'ottimizzazione interna che sembra garantire che la sottoquery venga valutata solo una volta. Non so se qualcuno al di fuori di Microsoft sia a conoscenza di come funziona esattamente questa ottimizzazione, ma puoi farlo se confronti i piani. Ecco il piano per la versione COALESCE:

Ed ecco il piano per la versione ISNULL:nota quanto è più semplice (e che la scansione avviene solo una volta):

Nel caso COALESCE la scansione avviene due volte. Ciò significa che la sottoquery viene valutata due volte, anche se non produce alcun risultato. Se aggiungi una clausola WHERE in modo tale che la sottoquery produca 0 righe, vedrai una disparità simile:le forme del piano potrebbero cambiare, ma vedrai comunque una doppia ricerca + ricerca o scansione per il caso COALESCE. Ecco un esempio leggermente diverso:

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

Il piano per la versione COALESCE questa volta - ancora una volta puoi vedere l'intero ramo che rappresenta la sottoquery ripetuta testualmente:

E ancora un piano molto più semplice, facendo circa metà del lavoro, usando ISNULL:

Puoi anche vedere questa domanda su dba.se per ulteriori discussioni:

Il mio suggerimento è questo (e puoi vedere i miei motivi nel suggerimento e nella domanda sopra):fidati ma verifica. Uso sempre COALESCE (perché è uno standard ANSI, supporta più di due argomenti e non fa cose altrettanto stravaganti con la precedenza del tipo di dati) a meno che So che sto usando una sottoquery come una delle espressioni (cosa che non ricordo di aver mai fatto al di fuori di un lavoro teorico come questo) o sto riscontrando un vero problema di prestazioni e voglio solo confrontare per vedere se COALESCE vs. ISNULL ha qualche sostanziale differenza di prestazioni (che al di fuori del caso di subquery, devo ancora trovare). Dal momento che utilizzo quasi sempre COALESCE con argomenti di tipi di dati simili, raramente devo fare altri test oltre a guardare indietro a ciò che ho detto in passato (sono stato anche l'autore di l'articolo di aspfaq segnalato da xQbert , 7 anni fa).