先読み(プリフェッチ)を使用して、より多くの(およびさまざまな数の)論理読み取りを実行する理由


8

SQL Serverでtpchデータベースを作成した後、以下のクエリを試しました。

    set statistics io on
    DBCC DROPCLEANBUFFERS;        
    select top 100 * from dbo.lineitem order by l_partkey;

テーブルのlineitemには、l_partkeyに非クラスター化インデックスがあります。上記のクエリを数回発行したところ、論理読み取りが毎回異なることがわかりました。

    Table 'lineitem'. Scan count 1, logical reads 1019, physical reads 4, read-ahead reads 1760, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1007, physical reads 4, read-ahead reads 1720, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1030, physical reads 4, read-ahead reads 1792, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

ここの投稿から:論理的な読み取りカウントは異なります。先読みの動作が原因である可能性があります。

しかし、正確に先読みがより論理的な読み取りを引き起こす理由は何ですか?SQL Serverの動作をどのように変更しますか?SQL Serverのように、とにかくキャッシュにあるため、より多くのインデックスページを読み取ることができますか?

とにかく、先読みを無効にして上記のクエリを再度発行しました。現在は、毎回同じ量の論理読み取りが報告されます。しかし、論理読み取りははるかに小さいです!!

    Table 'lineitem'. Scan count 1, logical reads 404, physical reads 160, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

だから私の質問は、先読み機能がなぜさらに多くのさまざまな論理読み取りカウントを引き起こす可能性があるのですか?

好奇心から、 "order by"なしで別のクエリを試しました。

    select top 100 * from dbo.lineitem

先読みなしの結果は次のとおりです。

    Table 'lineitem'. Scan count 1, logical reads 5, physical reads 3, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

これが先読みの結果です。

    Table 'lineitem'. Scan count 1, logical reads 15, physical reads 2, read-ahead reads 3416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

先読みがあるものは、まだより論理的な読み取りがあります。なぜ?

回答:


9

このORDER BY l_partkey例のクエリプランは、ほぼ確実に(先読みを使用して)非クラスター化インデックスを読み取り、次にキールックアップを実行して、カバーされていない列を取得します。

ルックアップの上のネストされたループ結合演算子は、おそらくルックアップに追加のプリフェッチ(WithOrderedPrefetch)を使用します。詳細については、私が書いた次の記事を参照してください。

また、リンクされたQ&Aの回答で述べたように、先読みの回数は、タイミングとストレージサブシステムの特性によって異なります。同じ種類の考慮事項が、ネストされたループ結合でのルックアッププリフェッチにも適用されます。

SQL Server は、インデックススキャンで必要になる可能性があるページの先読みを発行しますが、これはクエリの指定によって制限されないことに注意してくださいTOPTOPストレージエンジンによって制御される先読みのに対し、クエリプロセッサエレメントです。

アクティビティはまったく異なります。先読み(およびプリフェッチ)は、スキャン(またはルックアップ)で必要になる可能性があるページに対して非同期 I / Oを発行します

I / Oが実際に完了してクエリプロセッサで行を利用できるようにする順序(特に)に応じて、実際にタッチされた(論理読み取り)ページまたは物理的に読み取られたページの数は異なる場合があります。特に、Lookup遅延プリフェッチは、Lookupに必要なページがすでにメモリ内にあるかどうかを確認するときに、論理読み取りにも影響することに注意してください。

したがって、すべてがオーバーラップする操作の詳細なタイミングに帰着します。クエリプロセッサは、必要な行数(100)がトップイテレータで確認されるとすぐに、クエリ実行パイプラインのシャットダウンを開始します。その時点で発行または完了される非同期I / O(先読みまたはプリフェッチ)の数は、本質的に非決定的です。

トレースフラグ8744を使用してネストループ結合プリフェッチを無効にすると、これをさらに詳しく調べることができます。これWithOrderedPrefetchにより、ネストされたループ結合からプロパティが削除されます。通常OPTION (QUERYTRACEON 8744)はクエリ自体で使用します。いずれの場合も、プリフェッチされているキャッシュされたプランを再利用しないようにする必要があります。プランキャッシュを毎回クリアするか、を使用してクエリを強制的に再コンパイルしOPTION (RECOMPILE)ます。

論理読み取りは、クエリのためにアクセスされたキャッシュページの数の簡単な尺度です。先読み(および/またはプリフェッチ)が有効になっている場合、その先読みを発行するために、またはプリフェッチアクティビティの一部として、より多くの(そして異なる!)インデックスおよびデータページが操作される可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.