Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Paginação do lado do servidor no SQL Server


O CTE não é (necessariamente) "atualizado". Não é que inevitavelmente copiará todas as linhas em outro lugar e executará outras operações sobre a cópia (embora possa se comportar de modo que o otimizador decida que é melhor).

Se tomarmos esta simples consulta:
SELECT  *
FROM    (
        SELECT  *,
                ROW_NUMBER() OVER (ORDER BY id) rn
        FROM    mytable
        ) q
WHERE   rn BETWEEN 101 AND 110

e olhe para o seu plano, veremos algo assim:
  |--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)

Aqui, os registros são escaneados (em id ordem como a tabela está agrupada em id ), atribuído o ROW_NUMBER (é isso que Sequence Project faz) e passado para TOP que apenas interrompe a execução quando um certo limite é atingido (110 registros em nosso caso).

Esses 110 registros são passados ​​para Filter que só passa os registros com rn superior a 100.

A própria consulta verifica apenas 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.

em 3 páginas.

Agora vamos ver a consulta não paginada:
SELECT  *
FROM    mytable
ORDER BY
        id

Este é bem simples:leia tudo da mesa e cuspa.
  |--Clustered Index Scan(OBJECT:([ee].[dbo].[mytable].[PK__mytable__3213E83F29C2D227]), ORDERED FORWARD)

No entanto, olhar com facilidade não significa feito facilmente. A tabela é bem grande e precisamos fazer muitas leituras para retornar todos os 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.

Então, em poucas palavras, a consulta de paginação só sabe quando parar.