sql-server – 为什么这个连接基数估计如此之大?
原始查询中的派生表已被删除,并且投影已标准化.执行初始基数和选择性估计的树的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):
结果是对笛卡儿积的选择性为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行的固定猜测.
这是一个合理的期望,即使人们接受基数估计可以在不同的时间(基于成本的优化期间)在物理上不同但逻辑上和语义上相同的子树上发生 – 最终计划是一种最好的拼接在一起的最好的(每个备忘录组).缺乏计划范围的一致性保证并不意味着个人加入应该能够蔑视尊重,我明白了. 另一方面,如果我们最终猜测最后的手段,希望已经失去了,那么为什么还要费心呢.我们尝试了所有熟悉的技巧,然后放弃了.如果没有别的,那么狂野的最终估计是一个很好的警示标志,在编译和优化此查询期间并非所有内容都在CE内部完成. 当我尝试MCVE时,120 CE为原始查询产生了零(= 1)行最终估计(如嵌套的ISNULL),这与我的思维方式一样令人无法接受. 真正的解决方案可能涉及设计变更,允许在没有COALESCE或ISNULL的情况下进行简单的等连接,理想情况下是外键和其他约束对查询编译有用. (编辑:威海站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |