統計は最新ですが、推定値が間違っています


12

するとdbcc show_statistics ('Reports_Documents', PK_Reports_Documents)、レポートID 18698に対して次の結果が得られます。

ここに画像の説明を入力してください

このクエリの場合:

SELECT * 
FROM Reports_Documents 
WHERE ReportID = 18698 option (recompile)

クラスター化インデックスPK_Reports_Documentsを期待どおりにシークするクエリプランを取得します。

しかし、私を困惑させるのは、推定行数の誤った値です:

ここに画像の説明を入力してください

よると、この

サンプルクエリのWHERE句の値がヒストグラムのRANGE_HI_KEY値と等しい場合、SQL ServerはヒストグラムのEQ_ROWS列を使用して、等しい行の数を決定します

これは私が期待する方法でもありますが、実際にはそうではないようです。またRANGE_HI_KEY、提供されたヒストグラムに存在する他のいくつかの値を試してみてshow_statistics、同じことを経験しました。私の場合、この問題により、一部のクエリで非常に最適でない実行プランが使用され、実行時間が数分になるのに対し、クエリヒントで1秒で実行できるように思われます。

全体として:EQ_ROWS推定行数にヒストグラムが使用されていない理由と、誤った推定値はどこから来たのかを誰かが説明できますか?

もう少し(おそらく役立つ)情報:

  • 統計の自動作成はオンであり、すべての統計は最新です。
  • クエリされるテーブルには、約8000万行があります。
  • PK_Reports_Documentsなる組み合わせPKでありReportID INT、およびDocumentID CHAR(8)

クエリは合計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 毎晩実行して統計を更新するようにスケジュールされています。

回答:


10

これには簡単な解決策があります。

すべての_dta_...統計情報を削除し、DTA推奨事項の盲目的な適用を停止します。

詳しくは

特定の問題は、問題の列に複数セットの統計があることでした。追加のdta統計は、データのサンプリングによって作成されました(インデックスに関連付けられていない統計のデフォルトの動作)。

サンプリングされた統計の場合によくあることですが、結果のヒストグラムは、不正確なデータの全範囲をカバーしませんでした。質問のクエリは、たまたまヒストグラムの外にある値を選択したため、1行の推定値になりました。

同じ列に複数の統計セットが存在する場合のクエリオプティマイザーの正確な動作は完全には文書化されていません。サンプリングよりも「完全スキャン」統計を優先する傾向がありますが、古い統計よりも最近更新された統計も優先します。


これは確かに機能します。ただし、_dta_統計情報は作成しませんでした。DBを初めて見たときから統計情報がありました。しかし、推奨事項を使用すると、このような悪影響が生じる可能性があることは知りませんでした
...-user1151923
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.