CTE
nie jest (koniecznie) „aktualizowany”. Nie chodzi o to, że nieuchronnie skopiuje wszystkie wiersze w inne miejsce i wykona inne operacje na kopii (chociaż może zachowywać się tak, że optymalizator uzna, że jest to lepsze).
Jeśli weźmiemy to proste zapytanie:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
i spójrz na jego plan, zobaczymy coś takiego:
|--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)
Tutaj rekordy są skanowane (w id
kolejność, ponieważ tabela jest zgrupowana na id
), przypisał ROW_NUMBER
(to właśnie Sequence Project
robi) i przekazano do TOP
który zatrzymuje wykonanie po osiągnięciu określonego progu (110
rekordy w naszym przypadku).
Te 110 rekordów jest przekazywanych do Filter
który przekazuje rekordy tylko za pomocą rn
większe niż 100.
Samo zapytanie skanuje tylko 110
rekordy:
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.
na 3 stronach.
Zobaczmy teraz zapytanie niepodzielone na strony:
SELECT *
FROM mytable
ORDER BY
id
Ta jest całkiem prosta:przeczytaj wszystko ze stołu i wypluj.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Jednak łatwe szukanie nie oznacza łatwego wykonania. Tabela jest dość duża i musimy wykonać wiele odczytów, aby zwrócić wszystkie rekordy:
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.
Krótko mówiąc, zapytanie o paginację po prostu wie, kiedy przestać.