知识卡片
重复行破坏优化器的表达式变换能力
内容
禁止重复行最有力的实践依据,不是”重复行看起来不整洁”,而是重复行会直接破坏 优化器的查询重写能力。查询重写是优化器把一个关系表达式exp1(比如某用户查询) 转换成语义等价、但执行效率更优的表达式exp2的过程;这个转换合法的前提是exp1和 exp2必须产生完全相同的结果。书中用一个具体反例说明重复行如何摧毁这个前提: 针对同一个业务问题(”获得是螺丝或由S1供应的零件编号”),给出12种逻辑上应该 “等价”的SQL表述方式(分别组合了子查询/JOIN、UNION/UNION ALL、有无DISTINCT等 写法),结果这12种写法却产生了9种不同的重复度结果——有的产出P1出现9次,有的 只出现1次。这说明一旦系统里存在重复行,”表达式exp1和exp2产生相同结果”这个 优化器赖以转换的前提就不再自动成立,优化器即便想把某个写法自动转换成另一个 更高效的等价写法也不敢轻易这么做,重复行由此扮演了”优化抑制器”(optimization inhibitor)的角色。这个后果殃及多方:优化器代码本身更难写、更难维护、更容易 出错,产品更昂贵也更晚上市;系统实际性能可能低于本应达到的水平;用户不得不 自己花心思琢磨”怎么写这条查询才能拿到理论上最优的性能”——而这正是关系模型 从设计之初就想让用户完全摆脱的负担(呼应[[关系模型的声明式本质]])。最讽刺的 是,大多数用户压根不关心结果里到底有几个重复行,但优化器不知道用户不关心, 仍然会被这个用户根本不在意的差异不必要地束缚住手脚。
参考来源
- 位置:《SQL与关系数据库理论——如何编写健壮的SQL代码》第4章"不要重复,不要
null"4.1节"重复有什么问题"(源文件:OEBPS/text00043.html)
- 结论依据:原文明确"假设SQL是真正关系化的,那么一些本应有效的表达式变换及
对应的优化都会因为'重复'的存在而不再有效……这12个不同的表述方式产生9个不同
的结果……重复行扮演着优化抑制器(optimization inhibitor)这一角色……在大多数
情况下,用户可能不关心到底结果中会出现多少重复……优化器并不知道用户关不关心
这些差别,还是会被(不必要地)阻止进行本应进行的转换"。
- 原始内容:这12个不同的表述方式产生9个不同的结果……重复行扮演着优化抑制器
(optimization inhibitor)这一角色……用户会卷入性能问题之中……这是关系模型
明确表示要避免的情况。