当过滤器“大于”或“小于”时,用于估算行的公式有点愚蠢,但这是您可以得出的数字。
号码
使用步骤193,以下是相关数字:
RANGE_ROWS = 6624
EQ_ROWS = 16
AVG_RANGE_ROWS = 16.1956
上一步的RANGE_HI_KEY = 1999-10-13 10:47:38.550
当前步骤中的RANGE_HI_KEY = 1999-10-13 10:51:19.317
来自WHERE子句的值= 1999-10-13 10:48:38.550
公式
1)在两个范围高键之间找到毫秒
SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')
结果是220767 ms。
2)调整行数
我们需要找到每毫秒的行,但在此之前,我们必须从RANGE_ROWS中减去AVG_RANGE_ROWS:
6624-16.1956 = 6607.8044行
3)用调整后的行数计算每毫秒的行数:
6607.8044行/ 220767毫秒= 0.0299311行/毫秒
4)计算WHERE子句中的值与当前步骤RANGE_HI_KEY之间的ms
SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')
这给了我们160767毫秒。
5)根据每秒的行数计算此步骤中的行:
.0299311行/毫秒* 160767毫秒= 4811.9332行
6)还记得我们之前如何减去AVG_RANGE_ROWS吗?是时候添加它们了。现在我们已经完成了与每秒行数相关的计算,我们也可以安全地添加EQ_ROWS了:
4811.9332 + 16.1956 + 16 = 4844.1288
四舍五入,这就是我们的4844.13估计。
测试公式
我找不到关于为何在计算每毫秒行数之前减去AVG_RANGE_ROWS的文章或博客文章。我是能确认他们是占了估算,但仅在过去的毫秒-从字面上。
使用WideWorldImporters数据库,我进行了一些增量测试,发现行估计值的减少是线性的,直到步骤结束为止,在此步骤中,突然考虑了1x AVG_RANGE_ROWS。
这是我的示例查询:
SELECT PickingCompletedWhen
FROM Sales.Orders
WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'
我更新了PickingCompletedWhen的统计信息,然后得到了直方图:
DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')
为了了解随着我们接近RANGE_HI_KEY,估计的行数如何减少,我在整个步骤中收集了样本。减少是线性的,但是表现得好像等于AVG_RANGE_ROWS值的行数不是趋势的一部分...直到您击中RANGE_HI_KEY,然后突然下降,就像注销的未收债务一样。您可以在示例数据中看到它,尤其是在图形中。
请注意,行的稳步下降,直到我们达到RANGE_HI_KEY,然后突然减去最后一个AVG_RANGE_ROWS块的BOOM。在图中也很容易发现。
综上所述,AVG_RANGE_ROWS的奇数处理使计算行估计更加复杂,但是您始终可以调和CE的工作。
指数退缩呢?
指数退避是新的(自SQL Server 2014起)基数估计器使用的方法,该方法可在使用多个单列统计信息时获得更好的估计。由于此问题与一个单列统计有关,因此它不涉及EB公式。