2010-03-05 6 views
8

La seguente query utilizza un indice di ricerca su un indice sulla colonna LastModifiedTime.Index Seek vs. Clustered Index Scan: perché viene scelta la scansione?

SELECT 
     CONVERT(varchar, a.ReadTime, 101) as ReadDate, 
     a.SubID, 
     a.PlantID, 
     a.Unit as UnitID, 
     a.SubAssembly 
FROM dbo.Accepts a WITH (NOLOCK) 
WHERE a.LastModifiedTime BETWEEN '3/3/2010' And '3/4/2010' 
AND a.SubAssembly = '400' 

La domanda sotto, che è quasi identica alla query precedente, utilizza una scansione indice cluster, anziché l'indice sulla LastModifiedTime. Qualcuno può dirmi perché? E, cosa più importante, quello che posso fare per ottenere SQL Server per utilizzare l'indice sulla colonna LastModifiedTime, senza utilizzare un hint di indice.

Declare @LastModifiedTimeEnd dateTime 
Declare @LastModifiedTimeStart dateTime 

    SELECT 
      CONVERT(varchar, a.ReadTime, 101) as ReadDate, 
      a.SubID, 
      a.PlantID, 
      a.Unit as UnitID, 
      a.SubAssembly 
    FROM dbo.Accepts a WITH (NOLOCK) 
    WHERE a.LastModifiedTime BETWEEN @LastModifiedTimeStart And @LastModifiedTimeEnd 
    AND a.SubAssembly = '400' 

risposta

6

La domanda sotto, che è quasi identica alla query precedente, utilizza una scansione indice cluster, anziché l'indice sulla LastModifiedTime. Qualcuno può dirmi perché?

La domanda sotto non conosce i valori dei parametri durante la creazione del piano e presuppone che in generale, la scansione indice cluster è migliore.

E, cosa più importante, che cosa posso fare per ottenere SQL Server per utilizzare l'indice sulla colonna LastModifiedTime, senza utilizzare un suggerimento indice.

SELECT 
     CONVERT(varchar, a.ReadTime, 101) as ReadDate, 
     a.SubID, 
     a.PlantID, 
     a.Unit as UnitID, 
     a.SubAssembly 
FROM dbo.Accepts a WITH (NOLOCK) 
WHERE a.LastModifiedTime BETWEEN @LastModifiedTimeStart And @LastModifiedTimeEnd 
AND a.SubAssembly = '400' 
OPTION (OPTIMIZE FOR (@LastModifiedTimeStart = '3/3/2010', @LastModifiedTimeEnd = '3/4/2010')) 

In alternativa, è possibile aggiungere OPTION (RECOMPILE), che creerà il diverso piano di esecuzione ogni volta che si esegue la query, prendendo i valori dei parametri sul conto (parametro sniffing).

Questo, tuttavia, non garantisce che l'indice verrà utilizzato.

+0

sono confusa sul motivo per cui il pianificatore di query sarebbe assumere l'indice cluster è meglio. Indipendentemente da quali siano i parametri, si sta ancora confrontando una colonna specifica che ha un indice creato per essa. Qual è il punto di tale indice se è usato solo con parametri fissi? –

+0

@Kent: utilizzando un indice secondario per recuperare un intervallo di valori richiede unire l'indice indietro alla tabella. Quando l'intervallo è ampio, l'overhead del join supera il sovraccarico di ordinamento. – Quassnoi

+0

Vedo - grazie. Suppongo che una sorta di presunto sniffing dei parametri sia un comportamento predefinito. Presumibilmente usando '> = @LastModifiedTimeStart AND <= LastModifiedTimeEnd' precluderebbe anche l'uso dell'indice non cluster senza specificare' OPTION (RECOMPILE) '. –