セットアップ
カーディナリティの推定値を理解するのに苦労しています。テストのセットアップは次のとおりです。
- Stack Overflowデータベースの2010バージョン
- SQL Server 2017 CU15 + GDR(KB4505225)-14.0.3192.2
- 新しいCE(互換性レベル140)
私はこのプロシージャを持っています:
USE StackOverflow2010;
GO
CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
@CommentCount int
AS
BEGIN
SELECT *
FROM dbo.Posts p
WHERE
p.CommentCount = @CommentCount
OPTION (RECOMPILE);
END;
GO
dbo.Posts
テーブルに非クラスター化インデックスまたは統計がありません(にクラスター化インデックスがありますId
)。
このための推定プランを要求すると、「推定行」dbo.Posts
は1,934.99になります。
EXEC #sp_PostsByCommentCount @CommentCount = 51;
次の統計オブジェクトは、推定プランを要求したときに自動的に作成されました。
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
そのハイライトは次のとおりです。
- 統計のサンプルレートは1.81%と非常に低い(67,796 / 3,744,192)
- 31のヒストグラムステップのみが使用されました
- 「すべての密度」の値は次のとおりです
0.03030303
(33の異なる値がサンプリングされました) RANGE_HI_KEY
ヒストグラムの最後は50でEQ_ROWS
、1
質問
50を超える値(2,147,483,647まで)を渡すと、1,934.99行の推定値になります。 この推定値を生成するために使用される計算または値は何ですか? ちなみに、従来のカーディナリティ推定器は、1行の推定値を生成します。
私が試したこと
ここに私が持っていたいくつかの理論、私が試したもの、または私がこれを調べながら掘り出すことができた追加の情報があります。
密度ベクトル
最初は、を使用した場合と同じように、密度ベクトルになると考えましたOPTION (OPTIMIZE FOR UNKNOWN)
。しかし、この統計オブジェクトの密度ベクトルは3,744,192 * 0.03030303 = 113,460なので、そうではありません。
拡張イベント
イベントを収集する拡張イベントセッションを実行してみquery_optimizer_estimate_cardinality
ました(Paul Whiteのブログ投稿「カーディナリティの推定:密度統計の結合」から学びました)。
<CalculatorList>
<FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000"
CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />
<FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001"
TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true"
StatId="4" />
</CalculatorList>
したがって、CSelCalcAscendingKeyFilter
電卓が使用されたように見えます(他の電卓は、それが意味するものは何でも失敗したと言います)。この列はキーではなく、一意でも、必ずしも昇順でもありません。
その用語のいくつかのグーグルを行うと、いくつかのブログ投稿につながりました:
これらのポストは、新しいCEが密度ベクトルと統計の修正カウンターの組み合わせに基づいてこれらのヒストグラム外推定値に基づいていることを示しています。残念ながら、密度ベクトルは既に除外されており(と思う?!)、修正カウンターはゼロです(sys.dm_db_stats_properties
とにかく)。
トレースフラグ
フォレストは、TF 2363をオンにして、推定プロセスに関する詳細情報を取得することを提案しました。その出力から最も関連することはこれだと思います:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
これは突破口です(ありがとう、フォレスト!):その0.000516798
数(Selectivity="0.001"
上記のXE 属性では役に立たないように丸められているようです)にテーブル内の行数を掛けたものが、私が探していた推定値です(1,934.99)。
私はおそらく明らかな何かを見逃していますが、その選択性の値がCSelCalcAscendingKeyFilter
計算機内でどのように生成されるかをリバースエンジニアリングすることはできませんでした。