CTE
är inte (nödvändigtvis) "aktualiserad". Det är inte så att det oundvikligen kommer att kopiera alla rader någon annanstans och kommer att utföra andra operationer över kopian (även om det kan fungera så att optimeraren bestämmer att det är bättre).
Om vi tar den här enkla frågan:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
och titta på dess plan kommer vi att se något sånt här:
|--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)
Här skannas posterna (i id
ordning eftersom tabellen är klustrad på id
), tilldelade ROW_NUMBER
(detta är vad Sequence Project
gör) och skickas vidare till TOP
som bara stoppar exekveringen när en viss tröskel nås (110
register i vårt fall).
Dessa 110 poster skickas till Filter
som bara skickar posterna med rn
mer än 100.
Själva frågan skannar bara 110
poster:
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.
på 3 sidor.
Låt oss nu se den opaginerade frågan:
SELECT *
FROM mytable
ORDER BY
id
Den här är ganska enkel:läs allt från tabellen och spotta ut det.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Att se lätt ut betyder dock inte att det görs lätt. Tabellen är ganska stor och vi behöver läsa många gånger för att returnera alla poster:
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.
Så i ett nötskal vet sidnumreringsfrågan bara när den ska sluta.