El CTE
no es (necesariamente) "actualizado". No es que inevitablemente copiará todas las filas en otro lugar y realizará otras operaciones sobre la copia (aunque puede comportarse de manera que el optimizador decida que es mejor).
Si tomamos esta simple consulta:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
) q
WHERE rn BETWEEN 101 AND 110
y miramos su plan veremos algo como esto:
|--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)
Aquí, los registros se escanean (en id
orden ya que la tabla está agrupada en id
), asignó el ROW_NUMBER
(esto es lo que Sequence Project
lo hace) y se pasa a TOP
que simplemente detiene la ejecución cuando se alcanza cierto umbral (110
registros en nuestro caso).
Esos 110 registros se pasan a Filter
que solo pasa los registros con rn
mayor que 100.
La consulta en sí solo escanea 110
registros:
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 páginas.
Ahora veamos la consulta sin paginar:
SELECT *
FROM mytable
ORDER BY
id
Este es bastante simple:lee todo lo que hay en la tabla y escúpelo.
|--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)
Sin embargo, mirar fácilmente no significa hacerlo fácilmente. La tabla es bastante grande y necesitamos hacer muchas lecturas para devolver todos los registros:
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.
Entonces, en pocas palabras, la consulta de paginación solo sabe cuándo detenerse.