0

私はたくさんの行とたくさんの列を持つ非常に大きなテーブルを持っています(私はそれが悪いことを知っていますが、これは脇に置いておきましょう)。

具体的には、2つの列がありました- FinishTime, JobId。1つ目は行の終了時刻で、2つ目はそのIDです(一意ではありませんが、ほぼ一意です。同じIDを持つレコードはごくわずかです)。

jobidにインデックスがあり、finishtimeにインデックスがあります。

私たちは常に行を挿入しますが、ほとんどは終了時間順に並べられています。また、各インデックスの統計も定期的に更新しています。

今問題に:

フィルタを使用してクエリを実行すると、jobid==<some id> AND finishtime > <now minus 1 hour>このクエリには多くの時間がかかります。推定実行プランを表示すると、インデックスを超える方がはるかに優れているはずですが、プランはfinishtimeインデックスを超えることになっていることがわかります。jobidインデックスの統計を見ると、このインデックスの統計を更新しなかったため、サーバーは過去1時間のジョブ数が1であると「考えている」ことがわかります。

フィルタを使用してクエリを実行するとjobid==<some id> AND finishtime > <now minus 100 days>、SQL Serverは正しいインデックス(ジョブIDインデックス)を確認できるため、これはうまく機能します。

つまり、基本的に私の質問は、インデックス統計を常に更新しない場合(これには時間がかかる)、サーバーは最後のバケットを過ぎたレコードの数が1であると想定するのはなぜですか?

どうもありがとう

4

1 に答える 1

1

DBCC SHOW_STATISTICSを使用して、インデックスの統計に含まれるもののヒストグラムを取得できます。

DBCC SHOW_STATISTICS ( mytablename , myindexname ) 

日付ベースのレコードの場合、クエリは常に誤った統計になりがちです。これを実行すると、ヒストグラムの最後のバケットに[preor-to-today/after-today]の範囲のレコードがほとんどないことが示されます。ただし、他のすべてが等しい場合でも、SQL Serverは、両方が列を含まない単一列のインデックスである場合job_id、インデックスよりもインデックスを優先する必要があります。finishtimeこれは、job_id(int)がfinishtime(datetime)よりもルックアップが高速であるためです。

注:finishtimeクエリをカバーしている場合、ブックマークルックアップ操作が不要になるため、クエリオプティマイザがクエリを選択する際に大きな影響を与えます。

これに対抗するには、どちらか

  1. 統計を定期的に更新する
  2. データに複数のフィルター処理されたインデックス(2008以降の機能)を作成し、1つのパーティションをはるかに定期的に更新してテールエンドにします
  3. 機密性の高いクエリでインデックスヒントを使用する
于 2012-12-06T06:51:38.173 に答える