sql >> Base de Datos >  >> RDS >> Sqlserver

Paginación del lado del servidor en SQL Server

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.