Geo*_*son 16 sql-server sql-server-2014 cardinality-estimates
对于一个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
Run Code Online (Sandbox Code Playgroud)
查询计划
完整脚本
到目前为止我尝试过的
我深入研究了相关列的统计数据,发现密度向量显示了大约 11 亿个不同的值。SQL Server 2012 使用此估计并生成一个很好的计划。令人惊讶的是,SQL Server 2014 似乎忽略了统计数据提供的非常准确的估计值,而是使用了一个低得多的估计值。这会产生一个慢得多的计划,它没有保留几乎足够的内存并溢出到 tempdb。
我尝试了 trace flag 4199,但这并没有解决问题。最后,我尝试通过跟踪标志的组合来挖掘优化器信息(3604, 8606, 8607, 8608, 8612),如本文后半部分所示。但是,在它出现在最终输出树中之前,我无法看到任何解释错误估计的信息。
连接问题
Pau*_*ite 15
基数估计的推导方式对我来说肯定是违反直觉的。非重复计数计算(可通过扩展事件或跟踪标志 2363 和 3604 查看)是:
注意帽子。这的一般逻辑似乎非常合理(不能有更多不同的值),但上限是从采样的多列统计信息中应用的:
DBCC SHOW_STATISTICS
(BigFactTable, [PK_BigFactTable])
WITH
STAT_HEADER,
DENSITY_VECTOR;
Run Code Online (Sandbox Code Playgroud)
这显示了从 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;
Run Code Online (Sandbox Code Playgroud)
这里的密度是9.266754E-10,倒数其中是1079126528。
与此同时,一种明显的解决方法是使用完整扫描更新多列统计信息。另一种是使用原始基数估计器。
您打开的 Connect 项,SQL 2014 采样的多列统计信息覆盖了非前导列的更准确的单列统计信息,对于 SQL Server 2017标记为固定。
| 归档时间: |
|
| 查看次数: |
630 次 |
| 最近记录: |