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.
つまり、簡単に言えば、ページネーション クエリはいつ停止するかを知っているだけです。