SQL Server 2014 COUNT(DISTINCT x)は、列xの統計密度ベクトルを無視します


15

以下のためにCOUNT(DISTINCT)〜10億の異なる値を持っている、私は約3万行を持っていると推定ハッシュ集計でクエリプランを取得しています。

なんでこんなことが起こっているの?SQL Server 2012は適切な見積もりを生成しますが、これはSQL Server 2014のバグであり、Connectで報告する必要がありますか?

クエリと貧弱な見積もり

-- Actual rows: 1,011,719,166
-- SQL 2012 estimated rows: 1,079,130,000 (106% of actual)
-- SQL 2014 estimated rows: 2,980,240 (0.29% of actual)
SELECT COUNT(DISTINCT factCol5)
FROM BigFactTable
OPTION (RECOMPILE, QUERYTRACEON 9481) -- Include this line to use SQL 2012 CE

-- Stats for the factCol5 column show that there are ~1 billion distinct values
-- This is a good estimate, and it appears to be what the SQL 2012 CE uses
DBCC SHOW_STATISTICS (BigFactTable, _WA_Sys_00000005_24927208)
--All density   Average Length  Columns
--9.266754E-10  8               factCol5
SELECT 1 / 9.266754E-10
-- 1079126520.46229

クエリプラン

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

完全なスクリプト

以下は、統計のみのデータベースを使用した状況の完全な再現です

今まで試したこと

関連する列の統計を掘り下げたところ、密度ベクトルが推定約11億の異なる値を示していることがわかりました。SQL Server 2012はこの見積もりを使用して、適切な計画を作成します。驚くべきことに、SQL Server 2014は、統計によって提供される非常に正確な推定値を無視するように見え、代わりにはるかに低い推定値を使用します。これにより、tempdbに十分なメモリとスピルがほとんど確保されない、はるかに遅いプランが作成されます。

トレースフラグを試しました4199が、それで状況は修正されませんでした。最後に、この記事の(3604, 8606, 8607, 8608, 8612)後半で示されているように、トレースフラグの組み合わせを使用してオプティマイザー情報を掘り下げようとしました。しかし、最終的な出力ツリーに表示されるまで、悪い推定値を説明する情報を見ることができませんでした。

接続の問題

この質問への回答に基づいて、これをConnectの問題として提出しました。

回答:


14

カーディナリティの推定値の導出方法は、確かに直感に反するようです。個別のカウント計算(拡張イベントまたはトレースフラグ2363および3604で表示可能)は次のとおりです。

統計の導出

キャップに注意してください。これの一般的なロジックは非常に理にかなっているようですが(より明確な値はあり得ません)、キャップはサンプリングされた複数列統計から適用されます:

DBCC SHOW_STATISTICS 
    (BigFactTable, [PK_BigFactTable])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

PK統計

これは、3,439,431,721からサンプリングされた2,980,235行を、Col5レベルの3.35544E-07の密度ベクトルで示しています。その逆数により、2,980,235の多数の異なる値が実際の数学を使用して2,980,240に丸められます。

ここで問題となるのは、サンプリングされた統計が与えられた場合、個別の値の数に関してモデルがどのような仮定を行うべきかということです。私はそれを推定することを期待しますが、それは行われておらず、おそらく故意に行われます。

より直感的には、複数列の統計情報を使用する代わりに、Col5の密度を確認することを期待します(ただし、そうではありません)。

DBCC SHOW_STATISTICS 
    (BigFactTable, [_WA_Sys_00000005_24927208])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Col5の統計

ここで密度は9.266754E-10であり、これの逆数である1079126528

当面の明らかな回避策の1つは、フルスキャンで複数列の統計を更新することです。もう1つは、元のカーディナリティ推定量を使用することです。

開いたConnectアイテム、SQL 2014でサンプリングされた複数列統計は、先行しない列のより正確な単一列統計をオーバーライドし、SQL Server 2017で修正済みとマークされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.