9

SQL Server 2005にストアドプロシージャがあり、それを実行して実行プランを見ると、クラスター化インデックススキャンを実行していることがわかります。これには、84%のコストがかかります。Clustered Index Seekを取得するには、いくつか変更する必要があることを読みましたが、何を変更すればよいかわかりません。

私はこれでどんな助けにも感謝します。

ありがとう、

ブライアン

4

2 に答える 2

20

詳細がないと、問題が何であるか、さらには問題であるかどうかを推測するのは困難です。シークの代わりにスキャンを選択することは、多くの要因によって引き起こされる可能性があります。

  • クエリは、テーブル全体をカバーする結果セットを表します。つまり。クエリは単純SELECT * FROM <table>です。これは些細なケースであり、他に何も考慮する必要がなく、クラスター化されたインデックススキャンで完全にカバーされます。
  • オプティマイザーには代替手段がありません。
    • クエリはテーブル全体のサブセットを表しますが、フィルタリング述語はクラスター化されたキーの一部ではない列にあり、それらの列にも非クラスター化インデックスはありません。これらは、フルスキャン以外の代替プランではありません。
    • クエリには、クラスター化インデックスキーの列にフィルタリング述語がありますが、それらはSARGableではありません。フィルタリング述語は通常、SARGableにするために書き直す必要があります。適切な書き直しは、ケースごとに異なります。暗黙の変換ルールが原因で、より微妙な問題が発生する可能性があります。フィルタリング述語はですWHERE column = @valueが、列はVARCHAR(Ascii)で、@ valueはNVARCHAR(Unicode)です。
    • クエリには、クラスター化されたキーの列にSARGaleフィルタリング述語がありますが、左端の列はフィルタリングされません。つまり。clustredインデックスは列にあります(foo, bar)が、WHERE句はbar単独でオンになっています。
  • オプティマイザはスキャンを 選択します。
    • 代替手段が非クラスター化インデックスの場合、スキャン(または範囲シーク)しますが、クラスター化インデックスを使用することを選択します。クエリの非クラスター化インデックスカバレッジが不足しているため、通常、原因をインデックスの転換点まで追跡できます。投影。これはあなたの質問ではないことに注意してください。クラスター化されたインデックスシークではなく、クラスター化されていないインデックスシークを期待しているためです(質問が100%正確で文書化されていると仮定します...)
    • カーディナリティの見積もり。クエリコストの見積もりは、結果のカーディナリティの見積もり(つまり、一致する行数)を提供するクラスター化インデックスキーの統計に基づいています。単純なクエリでは、統計がどれほど離れていても、シークまたは範囲シークの推定値はスキャンの推定値よりも低くなるため、これは発生しませんが、複数のテーブルに結合とフィルターがある複雑なクエリでは、はより複雑であり、クエリオプティマイザが結合評価の順序をオブザーバーが期待するものと逆にするプランを選択する可能性があるため、プランにはシークが期待されるスキャンが含まれる場合があります。逆の順序を選択すると、(ほとんどの場合)正しくなるか、問題が発生する可能性があります(通常、統計が廃止されているか、パラメーターのスニッフィングが原因です)。
    • 注文保証。スキャンは保証された順序で結果を生成し、実行ツリーの上位の要素はこの順序の恩恵を受ける可能性があります(たとえば、ソートまたはスプールが削除されるか、ハッシュ/ネストされた結合の代わりにマージ結合が使用されます)。全体的に、明らかに遅いアクセスパスを選択した結果、クエリコストは向上します。

これらは、クラスター化インデックスのシークが予想されるときにクラスター化インデックススキャンが存在する理由のいくつかの簡単な指針です。質問は非常に一般的であり、8ボールに頼る以外に「なぜ」と答えることは不可能です。ここで、質問が適切に文書化され、明確に表現されているとすると、クラスター化インデックスのシークを期待するということは、クラスター化されたキー値に基づいて一意のレコードを検索していることを意味します。この場合、問題はWHERE句のSARGabilityにある必要があります。

于 2009-08-31T22:59:54.247 に答える
7

クエリにテーブル内の行の特定の割合以上が含まれている場合、オプティマイザはシークの代わりにスキャンを実行することを選択します。これは、その場合に必要なディスクIOが少なくなると予測するためです(シークの場合は、1つ必要です)。返される各行のインデックスのレベルごとのディスクIO)、スキャンの場合、テーブル全体の行ごとに1つのディスクIOのみがあります。

したがって、たとえばbツリーインデックスに5つのレベルがある場合、クエリによってテーブル内の行の20%以上が生成される場合、20%ごとに5つのIOを作成するよりも、テーブル全体を読み取る方が安価です。行...

プロセスのこのステップで返される行数を減らすために、クエリの出力をもう少し絞り込むことができますか?これは、スキャンよりもシークを選択するのに役立ちます。

于 2009-08-31T21:49:33.437 に答える