2010-01-05 18 views
7

Viene visualizzato un comportamento del piano di esecuzione bizzarro da SQL Server (2005).sql server: il numero stimato di righe non è disponibile

TableName: LOG
... contiene circa 1000 righe

  • ID int
  • Nome varchar (50)

Query:

SELECT * 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) as Row, 
       ID, Name 
      FROM Log) AS LogWithRowNumbers 
WHERE Row >= 1 
    AND Row <= 2 

E ' stima il num b di righe restituite come 9 (Anche se è ovvio 2 o meno).
Inoltre, rimuovendo il simbolo "e Riga < = 2" aumenterà il tempo di esecuzione di circa * 5. ("e Riga < = 2" e "e Row < = 9.999.999,999999 millions" si comportano allo stesso)

ho statistiche aggiornate. Ma ancora, questo comportamento è strano. L'aggiunta di Riga < 99999999999 renderà la query più veloce? perché ?

+0

Forza ragazzi, è facilmente riproducibile. Dove sono quei geni DBA quando ne hai bisogno? – Faruz

+0

@Faruz: non sono un DBA. Ma la query è più veloce quando si ha un solo criterio senza AND/OR (cioè ROW = 1). Come si comporta quando 'ROW = 1 OR ROW = 2' rispetto all'uso di'> = 'e' <= '. Crea un indice per la tabella 'Log' internamente? – shahkalpesh

+0

Riga = 1 o riga = 2 stimato 58 righe restituite ... Non crea un indice interno ma utilizza l'indice PK (ID). – Faruz

risposta

6

Non sono esperto del funzionamento interno/processo di ottimizzazione delle query di SQL Server, ma ecco i miei 2 pence (o centesimi se si preferisce).

Credo sia dovuto all'utilizzo del valore ROW_NUMBER() all'interno della clausola WHERE. Ad esempio, ho creato una tabella di esempio, popolata con 1000 righe dall'ID 1 a 1000 (ID come chiave primaria) come hai detto tu.

Se si prende la ROW_NUMBER(), e fare la query in base alla colonna ID come questo:

Select * FROM 
(
SELECT ID, Name 
FROM Log 
) 
as LogWithRowNumbers 
WHERE ID>=1 and ID<=2 

poi mostra correttamente conteggio delle righe come 2 - come previsto davvero.

Ora, lavorando a ritroso, aggiungere il ROW_NUMBER al SELEZIONA interiore, ma lasciare la clausola WHERE come-è come di seguito:

Select * FROM 
(
SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) AS RowNo, 
ID, Name 
FROM Log 
) 
as LogWithRowNumbers 
WHERE ID>=1 AND ID <=2 

Questo dimostra ancora il conteggio delle righe corrette 2.

Infine , impostare la clausola WHERE indietro per utilizzare RowNo come colonna su cui viene filtrato anziché ID, questo è quando il numero di righe stimato salta a 9.

Quindi, credo che sia l'uso della funzione ROW_NUMBER(), essendo filtrato nella clausola WHERE c ause. Quindi immagino che sia perché ci sono ovviamente statistiche migliori/più accurate disponibili su colonne di tabelle effettive rispetto a quelle presenti in questo valore prodotto dalla funzione.

Spero che questo almeno fornisca un buon punto di partenza, speriamo possa essere utile!

2

AdaTheDev è corretto. Il motivo per cui viene visualizzato questo comportamento è dovuto al fatto che SQL Server deve elaborare i numeri di riga per la tabella prima che possa utilizzarli nella clausola where.

Questo dovrebbe essere un modo più efficiente di ottenere gli stessi risultati:

SELECT TOP(2) ROW_NUMBER() OVER (ORDER BY ID DESC) as Row, 
ID, Name 
FROM Log 
ORDER BY ID DESC 
+0

Ricevo quello che stai dicendo, solo che è un esempio di una query che faccio. Solitamente recupero le righe 1-10, 10-20, ecc. Il problema è che devo farlo senza la "riga <999999" e che costa di più – Faruz

Problemi correlati