我们在 SQL Server 2016 SP2 CU12 Enterprise 上有一个查询,其中查询优化器估计只有 1 行会来自嵌套循环连接运算符,实际上有 108501 行返回。这导致Sort
操作员溢出到 TempDB。
对 Nested Loops Join 的内部(索引搜索)和外部输入(索引搜索)的估计是正确的。
我添加了跟踪标志 2363(选择性计算)和 3604(将输出重定向到消息窗口),在这里我发现有一个格式错误的直方图:
Plan for computation: CSelCalcExpressionComparedToExpression( QCOL: [Object1].Column1 x_cmpEq QCOL: [Object3].Column18 ) Loaded histogram for column QCOL: [Object1].Column1 from stats with id 1 *** WARNING: badly-formed histogram *** Loaded histogram for column QCOL: [Object3].Column18 from stats with id 9 Selectivity: 1.07973e-009 Stats collection generated: CStCollJoin(ID=4, CARD=1 x_jtLeftSemi) CStCollBaseTable(ID=1, CARD=5.01133e+007 TBL: Schema1.Table2 AS TBL: AA) CStCollFilter(ID=3, CARD=108210) CStCollBaseTable(ID=2, CARD=2.00511e+006 TBL: Schema1.Table1 AS TBL: A) End selectivity computation
以上只是部分输出,全文可以看这里
当我用全扫描更新格式错误的直方图时,估计是正确的(没有全扫描,这个问题没有解决)。
但是,只要在表中插入一条记录,直方图就会再次形成错误。
查询计划(带有错误直方图)可以在这里找到,在这里您可以找到更新统计信息后的查询计划。
未启用查询优化器修复。当我为此查询启用原始基数估计器时,使用跟踪标志 9481,我得到与更新统计信息后相同的查询计划。
什么会导致直方图格式不正确?
有没有办法解决这个问题?
我尝试了该PERSIST_SAMPLE_PERCENT
选项,但没有任何区别,直方图的格式也很糟糕。
这当然是一个错误。当 SQL Server 缩放不精确的直方图并遇到每个键显然具有多个值的唯一列时,就会发生这种情况。这在SQL Server 2016 中得到了部分解决,但在我看来,完整的修复只存在于 SQL Server 2017 上(我在 CU21 上测试过)。
使用
FULLSCAN
统计信息,原始 CE,升级到 SQL Server 2017,或等待完整修复被反向移植。演示
使用我的标准 Numbers 表创建脚本:
更新要采样的统计信息:
琐碎查询(仅请求估计计划):
跟踪输出包括:
在 Microsoft SQL Server 2016 (SP2-CU14) 上验证。
通过以下方式获得的统计直方图:
有如下条目:
在 SQL Server 2017 上,直方图为:
请注意,这些
EQ_ROWS
步骤是预先调整的,而不是依靠 CE 来完成。