web-dev-qa-db-ja.com

高度な断片化は問題ですか?

DBCC SHOWCONTIG scanning 'MyTable' table...
Table: 'MyTable' (2048062382); index ID: 1, database ID: 28
TABLE level scan performed.
- Pages Scanned................................: 1019182
- Extents Scanned..............................: 127400
- Extent Switches..............................: 127399
- Avg. Pages per Extent........................: 8.0
- Scan Density [Best Count:Actual Count].......: 100.00% [127398:127400]
- Logical Scan Fragmentation ..................: 0.01%
- Extent Scan Fragmentation ...................: 77.25%
- Avg. Bytes Free per Page.....................: 135.7
- Avg. Page Density (full).....................: 98.32%

スキャン密度= 100%は非常に良好であり、論理スキャンの断片化が1%未満の場合も優れていると私は読んだ。 77%のエクステントスキャンの断片化は私を悩ませますが、インターネットはそれを無視するように言っています。

単一テーブルのパフォーマンスの低いクエリを分析しています。最初の実行で約30秒、次に2回目以降の実行で200ミリ秒実行されます。この動作はDBCC DROPCLEANBUFFERSでリセットできます。

高いエクステントスキャンの断片化は重要な手がかりですか?

(そうでない場合は、おそらく単一テーブルのクエリに関する別の質問を追加します)。

7
Amy B

私の経験では、フルテーブルスキャンを実行している場合でも、エクステントの断片化がパフォーマンスに大きな影響を与える可能性は低く、より一般的なクエリパターンの場合は、ごくわずかです。これは、メモリに収まるキャッシュデータを使用するクエリの場合です。データがメモリ内にあり、ディスクから直接読み取られていない場合、明らかに、あらゆる種類の断片化はかなり問題になります。

これで、8 GBを超えるテーブルが作成されたため、エクステントの断片化がクエリに悪影響を与える可能性があります。このクエリが3400万行にわたるテーブルスキャンを使用していて、最悪(最初の実行時のみ)が30秒である場合、エクステントの断片化数を減らすことで大きな効果が得られる可能性はほとんどありません。その30秒はデータをメモリにロードするのに費やされており、断片化の程度を改善することでそこまで多くのことを購入できるとは思えません。このテーブルをメモリに保持するためのメモリがある場合は、起動ジョブまたはユーザーにクエリを待機させることなく定期的にクエリを実行するバックグラウンドプロセスを検討し、キャッシュ内で最新の状態を保つようにする必要があります。

ヘカトンはあなたのためかもしれません。

9
Aaron Bertrand

ConstantScan-> NestedLoop-> IndexSeek-> NestedLoop-> KeyLookupプラン

このプランは34.5M行のうち7,000行しか返さなかったため、テーブル全体にアクセスしませんでした。

ディスク全体のデータの総量は、テーブル全体のサイズに比べてごくわずかです。1;キールックアップ操作を実行するためのランダムシーク時間が支配的であるようです。断片化の問題の修正は、scan操作が関係する場合にのみ適用されます。アクセスパターンがここにあるようにランダムになると、断片化(および断片化メトリック)は無関係になります。

クエリの実行中にパフォーマンスモニターまたはリソースモニターでディスクアクティビティを監視することで、何が起こっているかを確認できるはずです。ディスクスループットが非常に低くなると思います。

私の分析が正しいと仮定して、特にコールドキャッシュでクエリの実行時間を改善するためのいくつかの提案(これらを組み合わせることができます)を次に示します。

  • ランダム読み取りをより適切に処理できるストレージサブシステムにデータファイルを配置します。おおまかな見積もりとして、30秒/ 7,000行は平均シーク時間の4ミリ秒程度であり、これは悪くないため、これは高額な提案になる可能性があります。

  • INCLUDE列を使用してクエリをカバーするように非クラスター化インデックスを変更します。これにより、キールックアップが不要になり、ランダムディスクアクティビティのほとんどが不要になります。これのために少し余分なストレージスペースを犠牲にしても、これはおそらく最良のソリューションです。うまくいけば、テーブルはそれほど広くありません。

1 行サイズがほぼ等しいと仮定します。


また、余談ですが DBCC SHOWCONTIG はかなり非推奨になりました-今後の置き換えは sys.dm_db_index_physical_stats

4
Jon Seigel