Le CTE
n'est pas (nécessairement) "actualisé". Ce n'est pas qu'il copiera inévitablement toutes les lignes ailleurs et effectuera d'autres opérations sur la copie (bien qu'il puisse se comporter de telle sorte que l'optimiseur décide que c'est mieux).
Si nous prenons cette requête simple :
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
et regardez son plan, nous verrons quelque chose comme ceci :
|--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)
Ici, les enregistrements sont scannés (en id
ordre car la table est regroupée sur id
), a attribué le ROW_NUMBER
(c'est ce que Sequence Project
fait) et transmis à TOP
qui arrête juste l'exécution lorsqu'un certain seuil est atteint (110
records dans notre cas).
Ces 110 enregistrements sont transmis à Filter
qui ne passe que les enregistrements avec rn
supérieur à 100.
La requête elle-même ne scanne que 110
enregistrements :
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.
en 3 pages.
Voyons maintenant la requête non paginée :
SELECT *
FROM mytable
ORDER BY
id
Celui-ci est assez simple :lisez tout ce qui se trouve sur le tableau et recrachez-le.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Cependant, regarder facilement ne signifie pas faire facilement. Le tableau est assez volumineux et nous devons effectuer plusieurs lectures pour renvoyer tous les enregistrements :
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.
Donc, en un mot, la requête de pagination sait juste quand s'arrêter.