2011-09-19 3 views
11

Codice regola analisi SR0007 per progetti di database di Visual Studio 2010 stabilisce che:Il wrapping di colonne nullable in ISNULL causa scansioni di tabelle?

dovrete indicare in modo esplicito come gestire i valori NULL nelle espressioni di confronto avvolgendo ogni colonna che può contenere un valore NULL in una funzione ISNULL.

Tuttavia codice regola analisi SR0006 viene violata quando:

Come parte di un confronto, l'espressione contiene un riferimento di colonna ... Il vostro codice potrebbe causare la scansione di un tavolo se si confronta un'espressione che contiene un riferimento di colonna.

Questo vale anche per ISNULL o ISNULL non ha mai esito in una scansione di tabella?

risposta

17

Sì, causa scansioni di tabelle. (anche se sembra essere ottimizzato se la colonna non è effettivamente annullabile)

La regola SR0007 è un consiglio estremamente scadente in quanto rende il predicato non attendibile e indica che qualsiasi indice sulla colonna sarà inutile. Anche se non vi è alcun indice sulla colonna, potrebbe comunque rendere imprecise le stime di cardinalità che interessano altre parti del piano.

La categorizzazione di esso nella categoria Microsoft.Performance è piuttosto divertente in quanto sembra essere stata scritta da qualcuno senza alcuna comprensione delle prestazioni della query.

Essa sostiene la logica è

Se il codice a confronto due valori NULL o un valore NULL con qualsiasi altro valore , il codice restituirà un risultato sconosciuto.

Mentre l'espressione stessa non valutare al unknown il codice restituisce un risultato completamente deterministico una volta capito che qualsiasi confronto =, <>, >, < ecc con NULL valutare come Unknown e che la clausola WHERE restituisce solo le righe in cui i espressione restituisce true.

È possibile che significano se ANSI_NULLS è disattivato, ma l'esempio fornito nella documentazione di WHERE ISNULL([c2],0) > 2; rispetto a WHERE [c2] > 2; non sarà comunque influenzato da questa impostazione. Questa impostazione

colpisce un confronto solo se uno degli operandi del confronto è o una variabile che è NULL o NULL letterale.

I piani di esecuzione che mostrano scansioni vs cercare o al di sotto

CREATE TABLE #foo 
    (
    x INT NULL UNIQUE 
) 

INSERT INTO #foo 
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) 
FROM sys.all_columns 

SELECT * 
FROM #foo 
WHERE ISNULL(x, 10) = 10 

SELECT * 
FROM #foo 
WHERE x = 10 

SELECT * 
FROM #foo 
WHERE x = 10 
     OR x IS NULL 

enter image description here

+0

Cosa c'è che la sintassi nella clausola ORDER 'BY'? (Ho cercato su Google ma è un po 'difficile da google per ...) – AakashM

+0

@AakashM - È il modo meno digitante che ho trovato finora di ordinare da una costante al fine di ottenere solo una sequenza crescente di numeri. 'over (order by (SELECT 0))' o 'over (ordine di @@ spid)' sono alternative. Non è possibile utilizzare un valore costante letterale come SQL Server ti dà un errore. La divisione per zero impedisce che venga trattata come una costante letterale. Non è possibile utilizzare '1/0' come le cose di SQL Server che si sta tentando di ordinare da un numero intero di colonne integer e genera un errore. –

+0

Oh capisco, '$' è interpretato come un letterale 'money' con valore zero! È una generosità sorprendente dal parser, devo dire :) – AakashM