目前,我正在尝试弄清楚SQL Server如何评估部分覆盖直方图步骤的范围谓词的基数。
在Internet上,在针对阶跃统计值和阶跃内统计值进行基数估计时,我遇到了一个类似的问题,保罗·怀特(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行。
请告诉我,在这种情况下,基数估算器如何评估?也许我在理解引用的公式时在某个地方犯了错误?