このサブクエリ(より大きなクエリの)の行の見積もりを改善しようとしています。見積もりは1266行を示しています。実際は117k行です。この特定のプロパティ(EAVスキーマ)には、2つの値(2と3)のみが定義されています。
declare @pPropVal smallint = 2;
select Value, ObjectId
from Oav.ValueArray PropName
where PropName.PropertyId = 897
and PropName.Value = @pPropVal
option (recompile)
クエリプランは、期待どおり、PropertyIdおよびValueのインデックスIX_ValueArray_PropValObjに適切なシーク述語を示しています。
([〜#〜] a [〜#〜])行の見積もりを改善する試みとして、追加の統計が追加され、行の見積もりがわずかに3041になりました。
create statistics [ST_SomePropertyName] ON [Oav].[ValueArray](PropertyId, Value, ObjectId)
where
(
PropertyId = 897
and [Value] is not null
)
with fullscan
ヒストグラムは単一の行を示しています。 HIキーはPropertyId(最初の列)であり、私が理解しているようにそれほど有用ではないため、密度情報を使用しています。
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
897 0 196026 0 1
All density Average Length Columns
1 4 PropertyId
0.5 8 PropertyId, Value
Name Updated Rows Rows Sampled Steps Density Average key length String Index Filter Expression Unfiltered Rows
ST_SomePropertyName May 20 2014 2:01PM 196026 196026 1 0 8 NO ([PropertyId]=(897) AND [Value] IS NOT NULL) 9317055
([〜#〜] b [〜#〜])PropertyId = 897にフィルターがあるので、次のような統計を再作成できると思いました。
create statistics [ST_SomePropertyName] ON [Oav].[ValueArray](Value, ObjectId)
where
(
PropertyId = 897
and [Value] is not null
)
with fullscan
ヒストグラムは私の目には便利に見えますが、元の推定値である1266に戻るため、推定器はそれを無視しているように見えます。
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
2 0 117760 0 1
3 0 78266 0 1
All density Average Length Columns
0.5 4 Value
5.101364E-06 12 Value, ObjectId
Name Updated Rows Rows Sampled Steps Density Average key length String Index Filter Expression Unfiltered Rows
ST_SomePropertyName May 20 2014 2:04PM 196026 196026 2 0 12 NO ([PropertyId]=(897) AND [Value] IS NOT NULL) 9317055
([〜#〜] c [〜#〜])固定値にフィルタリングすることはできますが(2番目の2列も必要ありません)、それはあまり実用的な解決策ではありません。これにより、正確な見積もりは117kになりました。
create statistics [ST_SomePropertyName] ON [Oav].[ValueArray](PropertyId)
where
(
PropertyId = 897
and [Value] = 2
)
with fullscan
ヒストグラム:
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
897 0 117760 0 1
([〜#〜] d [〜#〜])(元の質問に追加)値をより小さな範囲に制限するアプローチが役立ちます。ただし、範囲の値が均一でない場合、値が文字列ベースのフィールドである場合、または不明な場合でも、これは一般的に適切な回避策ではない可能性があります。
CREATE STATISTICS [ST_ListUnderBrand_897] ON [Oav].[ValueArray](PropertyId, Value)
WHERE
(
PropertyId = 897
and [Value] >= 1 and [Value] <= 20
)
with fullscan
これにより、約16kの見積もりが得られます。 [1,20]を正確な[2,3]に変更すると、約80kの見積もりが得られます。テーブルデータの値の実際の範囲は実際には使用されていないことは明らかであり(2列目であるため)、これは主にフィルター範囲に基づく推定値です。
[値]フィールドはsql_variantですが、クエリプランには暗黙的な変換が表示されないため、これは関連していないことに注意してください。
SQL ServerがBの統計を使用しないのはなぜですか?それをすべきですか?
これを修正するために利用できる他のオプションはありますか?
OPTION (RECOMPILE)
クエリヒントを使用し、SQL Server 2008 R2以降を実行していない限り、ローカル変数を使用している場合、フィルター処理されたインデックスと統計は機能しません。