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

Impaginazione lato server in SQL Server

Il CTE non è (necessariamente) "attualizzato". Non è che inevitabilmente copierà tutte le righe altrove ed eseguirà altre operazioni sulla copia (anche se potrebbe comportarsi in modo tale che l'ottimizzatore decida che è meglio).

Se prendiamo questa semplice domanda:

SELECT  *
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (ORDER BY id) rn
        FROM    mytable
        ) q
WHERE   rn BETWEEN 101 AND 110

e guardando il suo piano vedremo qualcosa del genere:

  |--Filter(WHERE:([Expr1003]>=(101) AND [Expr1003]<=(110)))
       |--Top(TOP EXPRESSION:(CASE WHEN (110) IS NULL OR (110)<(0) THEN (0) ELSE (110) END))
            |--Sequence Project(DEFINE:([Expr1003]=row_number))
                 |--Segment
                      |--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)

Qui, i record vengono scansionati (in id ordine poiché la tabella è raggruppata su id ), assegnato il ROW_NUMBER (questo è ciò che Sequence Project fa) e passati a TOP che interrompe l'esecuzione quando viene raggiunta una determinata soglia (110 record nel nostro caso).

Questi 110 record vengono passati a Filter che passa i record solo con rn maggiore di 100.

La query stessa esegue la scansione solo di 110 record:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 1 ms.

(строк обработано: 10)
Table 'mytable'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

in 3 pagine.

Ora vediamo la query non impaginata:

SELECT  *
FROM    mytable
ORDER BY
        id

Questo è piuttosto semplice:leggi tutto dal tavolo e sputalo.

  |--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)

Tuttavia, guardare facilmente non significa farlo facilmente. La tabella è abbastanza grande e abbiamo bisogno di fare molte letture per restituire tutti i record:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

(строк обработано: 1310720)
Table 'mytable'. Scan count 1, logical reads 2765, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 266 ms,  elapsed time = 11690 ms.

Quindi, in poche parole, la query di impaginazione sa solo quando fermarsi.