現時点では、ヒストグラムステップを部分的にカバーする範囲述部のカーディナリティをSQL Serverがどのように評価するかを理解しようとしています。
インターネット上で、ステップ内統計値の基数推定で、私は同様の質問に出くわし、Paul Whiteはそれに対してかなり興味深い答えを出しました。
Paulの答えによれば、述語> =および>のカーディナリティーを推定するための式(この場合、少なくとも120のカーディナリティー推定モデルにのみ興味があります)は次のとおりです。
>の場合:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
> =の場合:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
TransactionDate列と '20140614'から '20140618'までの日時の範囲を使用して、範囲の述語に基づいてAdventureWorks2014データベースの[Production]。[TransactionHistory]テーブルでこれらの式の適用をテストしました。
この範囲のヒストグラムステップの統計は次のとおりです。
式に従って、次のクエリの基数を計算しました。
SELECT COUNT(1)
FROM [AdventureWorks2014].[Production].[TransactionHistory]
WHERE [TransactionDate] BETWEEN '20140615 00:00:00.000' AND '20140616 00:00:00.000'
計算は、次のコードを使用して実行されました。
DECLARE @predStart DATETIME = '20140615 00:00:00.000'
DECLARE @predEnd DATETIME = '20140616 00:00:00.000'
DECLARE @stepStart DATETIME = '20140614 00:00:00.000'
DECLARE @stepEnd DATETIME = '20140618 00:00:00.000'
DECLARE @predRange FLOAT = DATEDIFF(ms, @predStart, @predEnd)
DECLARE @stepRange FLOAT = DATEDIFF(ms, @stepStart, @stepEnd)
DECLARE @F FLOAT = @predRange / @stepRange;
DECLARE @avg_range_rows FLOAT = 100.3333
DECLARE @distinct_range_rows INT = 3
DECLARE @EQ_ROWS INT = 0
SELECT @F AS 'F'
--for new cardinality estimator
SELECT @EQ_ROWS + @avg_range_rows * (@F * (@distinct_range_rows - 1) + 1) AS [new_card]
計算後、次の結果が得られました。
式によれば、150.5でしたが、オプティマイザーは225.75行で述語を推定します。述語の上部境界線を「20140617」に変更すると、オプティマイザーは既に250.833行を評価しますが、 200.6666行。
この場合、Cardinality Estimatorはどのように評価されますか?