Der CTE
nicht (notwendigerweise) "aktualisiert". Es ist nicht so, dass es zwangsläufig alle Zeilen an einen anderen Ort kopieren und andere Operationen über die Kopie ausführen wird (obwohl es sich so verhalten kann, dass der Optimierer entscheidet, dass es besser ist).
Nehmen wir diese einfache Abfrage:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
und schauen Sie sich den Plan an, dann sehen wir so etwas:
|--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)
Hier werden die Datensätze gescannt (in id
Reihenfolge, da die Tabelle auf id
geclustert ist ), der ROW_NUMBER
zugewiesen wurde (Dies ist, was Sequence Project
tut) und an TOP
weitergeleitet die die Ausführung einfach anhält, wenn ein bestimmter Schwellenwert erreicht ist (110
Aufzeichnungen in unserem Fall).
Diese 110 Datensätze werden an Filter
übergeben der die Datensätze nur mit rn
weitergibt größer als 100.
Die Abfrage selbst scannt nur 110
Aufzeichnungen:
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.
auf 3 Seiten.
Sehen wir uns nun die nicht paginierte Abfrage an:
SELECT *
FROM mytable
ORDER BY
id
Das ist ziemlich einfach:Lies alles aus der Tabelle und spuck es aus.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Einfach aussehen bedeutet jedoch nicht, dass es einfach ist. Die Tabelle ist ziemlich groß und wir müssen viele Lesevorgänge durchführen, um alle Datensätze zurückzugeben:
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.
Kurz gesagt, die Paginierungsabfrage weiß einfach, wann sie aufhören muss.