对于COUNT(DISTINCT)
具有约 10 亿个不同值的 a,我得到一个查询计划,其散列聚合估计只有约 300 万行。
为什么会这样?SQL Server 2012 产生了一个很好的估计,那么这是 SQL Server 2014 中的一个错误,我应该在 Connect 上报告吗?
查询及差评
-- 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
推导基数估计的方式对我来说肯定是违反直觉的。非重复计数计算(可通过扩展事件或跟踪标志 2363 和 3604 查看)为:
注意帽子。这的一般逻辑似乎非常合理(不能有更多不同的值),但上限是从抽样的多列统计数据中应用的:
这显示了从 3,439,431,721 行中抽取的 2,980,235 行,其 Col5 级别的密度向量为 3.35544E-07。其倒数给出了 2,980,235 的多个不同值,使用实数四舍五入为 2,980,240。
现在的问题是,给定抽样统计数据,模型应该对不同值的数量做出什么样的假设。我希望它可以推断,但这并没有完成,也许是故意的。
更直观地说,我希望它不会使用多列统计信息,而是查看 Col5 上的密度(但它没有):
这里的密度是 9.266754E-10,它的倒数是1,079,126,528。
同时,一个明显的解决方法是使用全扫描更新多列统计信息。另一种是使用原始基数估计器。
您打开的连接项SQL 2014 sampled multi-column statistics override more accurate single-column statistics for non-leading columns标记为Fixed for SQL Server 2017。