web-dev-qa-db-ja.com

インデックスシークが正しい行数を推定でき、ソート演算子が推定できないのはなぜですか?

次のような述語の関数を使用するクエリがあります。

commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)

40K行のcommentTypeにフィルター処理されたインデックスがあり、クエリを実行すると、インデックスシークの推定行数は非常に正確(約11K)ですが、次のステップ(ソート演算子)では、統計を完全に無視し、フィルターされたインデックスの行の総数を推定するだけです。

なぜこうなった?私は sargability の基本を知っており、正気を期すために、dateaddを実際の日付(2014-01-01)と置き換えることでテストしています。行の...

なぜこれが起こっているのですか、どうすれば修正できますか?決まった日を渡すことはできません...

11
MrKudz

DATEDIFF引数の2つを交換する推定機能のバグのため、あなたの推定は間違っていると思います。私はこれについてここで話します:

回避策は、DATEDIFF(2008+)を使用せずに13か月前の最初の日を計算することです。

DATEADD(MONTH, -13, DATEADD(DAY, 1-DATEPART(DAY,GETDATE()), CONVERT(DATE, GETDATE()));

見積もりに対処するpositiveではありません(フィルターされたインデックスでテストしていないため、実際に並べ替えが何を行っているのか、なぜ異なるのかわかりません計画および/またはクエリの残りの部分なしで推定します)。

Microsoftが推奨する修正はTF 4199を使用することですが、ここでそれを行う必要があるかどうかはわかりません。

もう1つのオプションは、使用しているSQL Serverのバージョンが最新のSP/CUであることを確認することです。これは、次のKB記事で修正されていると主張しているためです(ただし、TF 4199を使用する必要があります)。あなたが2014年以上でない限り):

この修正は、次のビルドで入手できます。

  • 2005 SP3 CU 15 (> = 9.00.4325 AND <= 9.00.4999)
  • 2005 SP4 CU 2 (> = 9.00.5259)
  • 2008 SP1 CU 1 (> = 10.00.2816.00 AND <= 10.00.3999)
  • 2008 SP2 CU (> = 10.00.4279.00 AND <= 10.00.5499)
  • 拡張により2008 SP3&SP4(> = 10.00.5500)
  • 2008 R2 CU 7 (10.50.1777.0)
  • 2008 R2 SP1 CU (> = 10.50.2769.0 AND <= 10.50.3999)
  • 拡張2008 R2 SP2およびSP3(> = 10.50.4000)
  • 拡張により、2012、2014、2016(> = 11.0)

(次回、SELECT @@VERSIONの結果を質問に含めてください。)

KB記事で、DATEDIFFは行数を過小評価できると述べていますが、これはシナリオで発生していることとは逆です。これは、修正が適用されないという意味ではありません。データと見ている範囲に応じて見積もりがどちらの方向にも進む可能性があるため、KB記事の表現は不正確だと思います。

上記の私のブログ投稿では、2014年以降はスワップが発生しないことが確認されています。安全のために、私はおそらくあなたの述語からDATEDIFFを破棄し、別の方法を使用して範囲の開始を計算します。 4199を過剰に使用したり、動的SQLを使用して不良スワップを防止したりすることはお勧めしません。

9
Aaron Bertrand