部分覆盖范围谓词的垂直度估计


13

目前,我正在尝试弄清楚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行。

请告诉我,在这种情况下,基数估算器如何评估?也许我在理解引用的公式时在某个地方犯了错误?


SQL SERVER 2014 12.0.5 SP2
ПавелКовалёв

Answers:


12

SQL Server在不同情况下使用不同的计算。您的示例不同于链接的“问答”,因为您的范围完全包含在一个步骤中。它没有跨越台阶边界。这也是两个端点而不是一个端点的间隔。编写BETWEEN与使用>=和编写两个单独的谓词相同<=

在一个步骤中间隔两个边界

修改了公式,以便在步骤中针对预期的不同值的数量执行线性插值,并反映出现在指定了两个范围终点(并假设存在于直方图步骤中)而不是一个。

使用问题中给出的直方图步骤:

问题直方图步骤

对于带有的查询BETWEEN '20140615' AND '20140616',计算结果为:

DECLARE
    @Q1 float = CONVERT(float, CONVERT(datetime, '2014-06-15')),
    @Q2 float = CONVERT(float, CONVERT(datetime, '2014-06-16')),
    @K1 float = CONVERT(float, CONVERT(datetime, '2014-06-14')),
    @K2 float = CONVERT(float, CONVERT(datetime, '2014-06-18')),
    @RANGE_ROWS float = 301,
    @DISTINCT_RANGE_ROWS float = 3;

DECLARE
    @S1 float = (@Q1 - @K1) / (@K2 - @K1),
    @S2 float = (@Q2 - @K1) / (@K2 - @K1);

DECLARE
    @F float = @S2 - @S1;

DECLARE
    @AVG_RANGE_ROWS float = @RANGE_ROWS / @DISTINCT_RANGE_ROWS;

SELECT
    @AVG_RANGE_ROWS * ((@F * (@DISTINCT_RANGE_ROWS - 2)) + 2);

...给出225.75。改变@Q2来自'20140616''20140617'给出的结果是250.833

两种结果均与问题中给出的结果相符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.