dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)
を実行すると、レポートID 18698に対して次の結果が得られます。
このクエリの場合:
_SELECT *
FROM Reports_Documents
WHERE ReportID = 18698 option (recompile)
_
クラスター化インデックスを_PK_Reports_Documents
_で期待どおりにシークさせるクエリプランを取得します。
しかし、私を困惑させるのは、推定行数の誤った値です。
this によると:
サンプルクエリのWHERE句の値がヒストグラムのRANGE_HI_KEYの値と等しい場合、SQL ServerはヒストグラムのEQ_ROWS列を使用して、等しい行の数を決定します
これは私が期待する方法でもありますが、実際にはそうではないようです。また、_RANGE_HI_KEY
_によって提供されるヒストグラムに存在する他の_show_statistics
_値をいくつか試し、同じことを経験しました。私の場合、この問題により、一部のクエリで最適化されていない実行プランが使用され、実行時間は数分になるようですが、クエリヒントを使用すると1秒で実行できます。
全体として:ヒストグラムの_EQ_ROWS
_が推定行数に使用されない理由と、誤った推定がどこから来たのか、誰かが私に説明できますか?
もう少し(おそらく役立つ)情報:
PK_Reports_Documents
_は、_ReportID INT
_とDocumentID CHAR(8)
で構成されるPKの組み合わせです。クエリは、合計5つの異なる統計オブジェクトをロードしているようです。これらのオブジェクトにはすべて、ReportID
+テーブルのいくつかの他の列が含まれています。それらはすべて新しく更新されました。以下の表の_RANGE_HI_KEY
_は、ヒストグラムの最高の上限列値です。
_+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| name | stats_id | auto_created | user_created | Leading column Type | RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| PK_Reports_Documents | 1 | 0 | 0 | Stationary | 18722 | 0 | 2228,526 | 0 | 1 |
| _dta_index_Reports_Documents_42_1629248859__K1_K63_K14_K13_K22_K23_72_6 | 62 | 0 | 0 | Stationary | 18698 | 0 | 2228,526 | 0 | 1 |
| _dta_stat_1629248859_1_1_59 | 76 | 0 | 1 | Stationary | 18686 | 50,56393 | 1 | 0 | 13397,04 |
| _dta_stat_1629248859_1_22_14_18_12_6 | 95 | 0 | 1 | Stationary | 18698 | 0 | 2228,526 | 0 | 1 |
| _dta_stat_1629248859_1_7_14_4_23_62 | 96 | 0 | 1 | Stationary | 18698 | 56,63327 | 21641,5 | 0 | 14526,44 |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
_
_sp_updatestats
_は、統計を更新するために毎晩実行するようにスケジュールされています。
これには簡単な解決策があります:
すべての_dta_...
統計情報を取得し、DTAの推奨事項を盲目的に適用するのをやめます。
詳細
特定の問題は、問題の列に複数の統計セットがあったことです。追加のdta
統計は、データのサンプリングによって作成されました(インデックスに関連付けられていない統計のデフォルトの動作)。
サンプリングされた統計の場合によくあることですが、結果のヒストグラムは基礎となるデータの全範囲をカバーしていませんでした。問題のクエリは、たまたまヒストグラムの外の値を選択したため、1行の推定値が得られました。
同じ列に統計の複数のセットが存在する場合のクエリオプティマイザーの正確な動作は、完全に文書化されていません。サンプリングよりも「フルスキャン」統計を優先する傾向がありますが、古い統計よりも最近更新された統計を優先します。