2

SQL サーバーが一般的なテーブル式と ROW_NUMBER を使用して読み取りを減らし、パフォーマンスを向上させる方法について少し混乱しています。クエリが ROW_NUMBER を使用して順序付けできるようにするために、通常のクエリで実行する必要があるすべての読み取りを、式で実際化されたテーブルで実行する必要がないのはなぜですか?

4

1 に答える 1

4

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れます (この場合はレコード)。

100 を超えるFilterレコードのみが渡される 110 のレコードが渡されます。rn

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.

つまり、簡単に言えば、ページネーション クエリはいつ停止するかを知っているだけです。

于 2013-01-18T09:53:17.577 に答える