CTE
не е (непременно) "актуализирано". Не че той неизбежно ще копира всички редове другаде и ще извърши други операции върху копието (въпреки че може да се държи така, че оптимизаторът реши, че е по-добре).
Ако вземем тази проста заявка:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
и погледнете плана му, ще видим нещо подобно:
|--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)
Тук записите се сканират (в id
ред, тъй като таблицата е групирана на id
), присвоен ROW_NUMBER
(това е Sequence Project
прави) и предадени на TOP
което просто спира изпълнението при достигане на определен праг (110
записи в нашия случай).
Тези 110 записа се предават на Filter
който предава само записите с rn
по-голямо от 100.
Самата заявка сканира само 110
записи:
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.
на 3 страници.
Сега нека видим нестраницираната заявка:
SELECT *
FROM mytable
ORDER BY
id
Този е доста прост:прочетете всичко от таблицата и го изплюйте.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Да изглеждаш лесно обаче не означава да се направи лесно. Таблицата е доста голяма и трябва да направим много четения, за да върнем всички записи:
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.
И така, накратко, заявката за пагиниране просто знае кога да спре.