我很难在关系代数中优化这个SQL查询:
SELECT * FROM R1, R2, R3, R4
WHERE (R1.A = '1' OR (R2.B = '2' AND R3.C = R4.C)) AND R4.D = '4'
我将它翻译成以下关系代数声明:
σ{R1.A='1' ∨ (R2.B='2' ∧ R3.C=R4.C) ∧ R4.D='4'}(R1 × R2 × R3 × R4)
我的问题是,我真的不知道如何优化where语句。
我知道我可以将最后一个条件转换为σ{R4.D='4'}(R4)
并将其直接向下移动到R4。
存在某种优化规则,但我真的不知道如何处理OR。 Rules for Logical Query Optimization
但我该如何优化剩下的? 我想过使用分配规则将其转换为KNF,
(R1.A='1' ∨ R2.B='2') ∧ (R1.A='1' ∨ R3.C=R4.C)
这将允许我独立处理两个子句。但我不知道如何继续,尤其是我应该加入或制作笛卡尔产品的顺序。
这是运营商树,我画:
答案 0 :(得分:1)
在查询优化期间处理析取的一种好方法是将选择条件转换为析取范式(DNF),然后将选择重写为选择联合(每个析取一个)。
即。在此处应用规则#2:https://en.wikipedia.org/wiki/Relational_algebra#Breaking_up_selections_with_complex_conditions
作为查询优化中的大多数技巧,它在某些情况下运行良好而在其他情况下运行良好 - 这就是为什么SQL优化器搜索计划空间,试图找到一个合适的计划。
答案 1 :(得分:1)
联盟是不可能的,因为它需要相同类型的列。 我现在得到了导师的正式解决方案。 正如我已经想到的那样,需要使用分布规则将其转换为将其转换为KNF,以便我有两个子句单独的子句。