加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – 为什么这个连接基数估计如此之大?

发布时间:2021-01-12 07:37:27 所属栏目:MsSql教程 来源:网络整理
导读:我正在经历我认为对以下查询的不可能高的基数估计: SELECT dm.PRIMARY_IDFROM( SELECT COALESCE(d1.JOIN_ID,d2.JOIN_ID,d3.JOIN_ID) PRIMARY_ID FROM X_DRIVING_TABLE dt LEFT OUTER JOIN X_DETAIL_1 d1 ON dt.ID = d1.ID LEFT OUTER JOIN X_DETAIL_LINK lnk

原始查询中的派生表已被删除,并且投影已标准化.执行初始基数和选择性估计的树的SQL表示形式为:

SELECT 
    PRIMARY_ID = COALESCE(d1.JOIN_ID,d3.JOIN_ID)
FROM X_DRIVING_TABLE dt
LEFT OUTER JOIN X_DETAIL_1 d1
    ON dt.ID = d1.ID
LEFT OUTER JOIN X_DETAIL_LINK lnk 
    ON d1.LINK_ID = lnk.LINK_ID
LEFT OUTER JOIN X_DETAIL_2 d2 
    ON dt.ID = d2.ID
LEFT OUTER JOIN X_DETAIL_3 d3 
    ON dt.ID = d3.ID
INNER JOIN X_LAST_TABLE lst 
    ON lst.JOIN_ID = COALESCE(d1.JOIN_ID,d3.JOIN_ID)

(另外,重复的COALESCE也存在于最终计划中 – 一次在最终的Compute Scalar中,一次在内部连接的内侧).

注意最后的加入.此内连接(根据定义)是X_LAST_TABLE和前面的连接输出的笛卡尔积,其中应用了lst.JOIN_ID = COALESCE(d1.JOIN_ID,d3.JOIN_ID)的选择(连接谓词).笛卡尔积的基数仅为481577 * 94025 = 45280277425.

为此,我们需要确定并应用谓词的选择性.不透明的扩展COALESCE树(根据UNION和IIF,记住)的组合以及对关键信息,派生直方图和早期“不寻常”多数冗余多对多外连接组合的频率的影响意味着CE无法以任何正常方式得出可接受的估计值.

结果,它进入猜猜逻辑.猜测逻辑中等复杂,尝试了各种“受过教育”的猜测和“没那么受过教育”的猜测算法.如果没有找到更好的猜测基础,模型使用最后的猜测,对于相等比较,它是:sqllang!x_Selectivity_Equal = fixed 0.1 selective(10%guess):

06002

结果是对笛卡儿积的选择性为0.1:481577 * 94025 * 0.1 = 4528027742.5(~4.52803e 009),如前所述.

重写

当有问题的连接被注释掉时,产生了更好的估计,因为避免了固定选择性“最后的猜测”(关键信息由1-M连接保留).估计的质量仍然很低,因为COALESCE连接谓词根本不是CE友好的.我想,修改后的估计对人类来说至少看起来更合理.

当查询使用外部联接写入最后放置的X_DETAIL_LINK时,启发式重新排序可以将其与最终内部联接交换到X_LAST_TABLE.将内连接放在问题外连接旁边,可以提供有限的早期重新排序机会以改进最终估计,因为大多数冗余的“不寻常”多对多外连接的影响来自于棘手的选择性估计对于COALESCE.同样,估计数比固定猜测要好一些,并且可能不会经得起在法庭上确定的交叉询问.

重新排序内部和外部联接的混合是困难且耗时的(即使第2阶段完全优化仅尝试有限的理论移动子集).

在Max Vernon的回答中建议的嵌套ISNULL设法避免纾困的固定猜测,但最终估计是一个不可能的零行(为了正派而提升到一行).对于计算所具有的所有统计基础,这也可以是1行的固定猜测.

I would expect a join cardinality estimate between 0 and 481577 rows.

这是一个合理的期望,即使人们接受基数估计可以在不同的时间(基于成本的优化期间)在物理上不同但逻辑上和语义上相同的子树上发生 – 最终计划是一种最好的拼接在一起的最好的(每个备忘录组).缺乏计划范围的一致性保证并不意味着个人加入应该能够蔑视尊重,我明白了.

另一方面,如果我们最终猜测最后的手段,希望已经失去了,那么为什么还要费心呢.我们尝试了所有熟悉的技巧,然后放弃了.如果没有别的,那么狂野的最终估计是一个很好的警示标志,在编译和优化此查询期间并非所有内容都在CE内部完成.

当我尝试MCVE时,120 CE为原始查询产生了零(= 1)行最终估计(如嵌套的ISNULL),这与我的思维方式一样令人无法接受.

真正的解决方案可能涉及设计变更,允许在没有COALESCE或ISNULL的情况下进行简单的等连接,理想情况下是外键和其他约束对查询编译有用.

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读