次に示す簡単なAdventureWorksクエリと実行計画を検討してください。クエリにはに接続された述語が含まれていAND
ます。オプティマイザーのカーディナリティの推定値は41,211行です。
-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
デフォルト統計の使用
単一列の統計のみを指定すると、オプティマイザは各述語のカーディナリティを個別に推定し、結果の選択度を乗算することによりこの推定値を生成します。このヒューリスティックは、述語が完全に独立していることを前提としています。
クエリを2つの部分に分割すると、計算が見やすくなります。
-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336;
Transaction Historyテーブルには合計113,443行が含まれているため、68,336.4の見積もりは、この述部の選択性68336.4 / 113443 = 0.60238533を表します。この推定値は、TransactionID
列のヒストグラム情報とクエリで指定された定数値を使用して取得されます。
-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
この述部の推定選択性は、68413.0 / 113443 = 0.60306056です。この場合も、述部の定数値とTransactionDate
統計オブジェクトのヒストグラムから計算されます。
述部が完全に独立していると仮定すると、2つの述部を乗算することにより、2つの述部の選択性を推定できます。最終的なカーディナリティの推定値は、結果の選択度にベーステーブルの113,443行を乗算することによって取得されます。
0.60238533 * 0.60306056 * 113443 = 41210.987
丸め後、これは元のクエリで見られた41,211の推定値です(オプティマイザーは内部で浮動小数点演算も使用します)。
素晴らしい見積もりではありません
TransactionID
そしてTransactionDate
列は、(単調頻繁に行うキーと日付列を増やすなど)のAdventureWorksデータセット内の密接な関係を持っています。この相関は、独立性の仮定に違反していることを意味します。結果として、実行後のクエリプランには、推定41,211行ではなく68,095行が表示されます。
トレースフラグ4137
このトレースフラグを有効にすると、述語の結合に使用されるヒューリスティックが変更されます。完全に独立していると仮定する代わりに、オプティマイザーは、2つの述部の選択性が十分に近く、相関している可能性が高いと見なします。
-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);
TransactionID
述部だけで68,336.4行が推定され、述部だけで68,413行が推定されたことを思い出してくださいTransactionDate
。オプティマイザーは、選択性を乗算するのではなく、これら2つの推定値のうち低い方を選択しました。
もちろん、これは単なるヒューリスティックですが、相関するAND
述語を使用したクエリの推定値を改善するのに役立つ可能性があります。各述語は考えられる相関について考慮され、多くのAND
句が関係する場合は他の調整が行われますが、その例はその基本を示すのに役立ちます。
複数列の統計
これらは相関のあるクエリで役立ちますが、ヒストグラム情報は依然として統計の先頭の列のみに基づいています。したがって、以下の複数列統計の候補は重要な点で異なります。
CREATE STATISTICS
[stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
(TransactionID, TransactionDate);
CREATE STATISTICS
[stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
(TransactionDate, TransactionID);
それらのうちの1つだけを見ると、唯一の追加情報は「すべて」の密度の追加レベルであることがわかります。ヒストグラムには、TransactionDate
列に関する詳細情報のみが含まれています。
DBCC SHOW_STATISTICS
(
'Production.TransactionHistory',
'stats Production.TransactionHistory TransactionDate TransactionID'
);
これらの複数列の統計を適切に配置すると...
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
...実行計画には、単一列の統計のみが利用可能な場合とまったく同じ推定値が表示されます。
Statistics objects on multiple columns also store statistical information about the correlation of values among the columns