SQL Server 2014 COUNT(DISTINCT x)忽略列x的统计信息密度向量


15

对于COUNT(DISTINCT)具有约10亿个不同值的,我正在获得一个查询计划,该计划的哈希汇总估计只有300万行。

为什么会这样呢?SQL Server 2012提供了一个很好的估计,所以这是我应该在Connect上报告的SQL Server 2014中的错误吗?

查询和差评

-- Actual rows: 1,011,719,166
-- SQL 2012 estimated rows: 1,079,130,000 (106% of actual)
-- SQL 2014 estimated rows: 2,980,240 (0.29% of actual)
SELECT COUNT(DISTINCT factCol5)
FROM BigFactTable
OPTION (RECOMPILE, QUERYTRACEON 9481) -- Include this line to use SQL 2012 CE

-- Stats for the factCol5 column show that there are ~1 billion distinct values
-- This is a good estimate, and it appears to be what the SQL 2012 CE uses
DBCC SHOW_STATISTICS (BigFactTable, _WA_Sys_00000005_24927208)
--All density   Average Length  Columns
--9.266754E-10  8               factCol5
SELECT 1 / 9.266754E-10
-- 1079126520.46229

查询计划

在此处输入图片说明

完整脚本

这是使用仅统计数据库的情况的完整再现

到目前为止我尝试过的

我对相关列的统计数据进行了挖掘,发现密度向量显示出约11亿个不同的值。SQL Server 2012使用此估计并制定了一个好的计划。令人惊讶的是,SQL Server 2014似乎忽略了统计数据提供的非常准确的估计,而是使用了低得多的估计。这将产生一个慢得多的计划,该计划无法保留几乎足够的内存并溢出到tempdb。

我尝试了trace flag 4199,但是并不能解决问题。最后,我尝试通过跟踪标记的组合来挖掘优化器信息(3604, 8606, 8607, 8608, 8612),如本文后半部分所示。但是,直到它出现在最终输出树中之前,我看不到任何信息来解释该错误的估计。

连接问题

基于此问题的答案,我也将此问题作为Connect中的一个问题

Answers:


14

基数估计的推导方式对我来说显然是违反直觉的。非重复计数计算(可通过扩展事件或跟踪标志2363和3604查看)是:

统计推导

注意瓶盖。这样做的一般逻辑似乎非常合理(不能有更多不同的值),但是上限是从抽样的多列统计信息中得出的:

DBCC SHOW_STATISTICS 
    (BigFactTable, [PK_BigFactTable])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

PK统计

这表明从3,439,431,721中取样的2,980,235行具有在Col5级别为3.35544E-07的密度矢量。倒数给出了2,980,235的多个不同值,使用真实数学将其舍入为2,980,240。

现在的问题是,给定抽样统计数据,模型应该对不同值的数量做出哪些假设。我希望它可以推断出来,但是那没有完成,也许是故意的。

更直观地说,我希望与其使用多列统计信息,不如查看Col5上的密度(但事实并非如此):

DBCC SHOW_STATISTICS 
    (BigFactTable, [_WA_Sys_00000005_24927208])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Col5统计

这里的密度是9.266754E-10,倒数其中是1079126528

同时,一种明显的解决方法是使用完整扫描更新多列统计信息。另一种是使用原始基数估计器。

你打开了连接项目,SQL 2014取样的多列统计信息覆盖非前导列更准确单列统计,被标记为固定为SQL Server 2017年。

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.