【问题标题】:Stuck with Logical SQL Query optimizations in Relational Algebra (OR in WHERE)陷入关系代数(或在 WHERE)中的逻辑 SQL 查询优化
【发布时间】:2015-06-05 09:06:38
【问题描述】:

我坚持在关系代数中优化这个 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

但是我如何优化其余的 where 呢? 我想过用分配规则把它变成KNF,

(R1.A='1' ∨ R2.B='2')  ∧ (R1.A='1'  ∨  R3.C=R4.C) 

这将允许我独立处理这两个子句。但我不知道如何继续,尤其是我应该以什么顺序加入或制作笛卡尔积。

这是运算符树,我画了:

【问题讨论】:

  • “优化”到底是什么意思?这和 SQLite 有什么关系?
  • @CL 优化意味着,使用关系代数的逻辑规则来降低评估成本并优化查询运算符的顺序,例如尽可能向下移动选择等。用 sqlite 标记,因为 SQL 语法适用于 sqlite(我使用 sqlite 作为数据库系统)示例:cs.uni-paderborn.de/fileadmin/Informatik/AG-Boettcher/Lehre/…
  • 我可能不对,但在您的翻译中,您省略了一对括号。在原始查询中,您有:(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'
  • 在现实世界中,我会将R4.D 检查分配到OR 的操作数中,以便SQLite 能够应用OR optimization,如果它愿意的话。这主要取决于索引的存在,但这种物理考虑不是您当前任务的一部分。无论如何,在R3/R4 加入之前进行R4.D 检查应该会提高选择性。
  • @T_G 是的,你是对的。

标签: sql sqlite relational-algebra


【解决方案1】:

在查询优化期间处理析取的一个好方法是将选择条件转换为析取范式(DNF),然后将选择重写为选择的联合(每个析取一个)。

即在此处应用规则 #2:https://en.wikipedia.org/wiki/Relational_algebra#Breaking_up_selections_with_complex_conditions

与查询优化中的大多数技巧一样,它在某些情况下效果很好,而在其他情况下却不行 - 这就是 SQL 优化器搜索计划空间并试图提出一个体面的计划的原因。

【讨论】:

  • 但 UNION 操作数必须具有相同的列集。 DNF 不保证。 (即它的 OR 不映射到 UNION。)对于这个问题,没有足够的信息来满足这一点,除非你将所有关系的两个连接联合起来,这不会是一种优化。 (请参阅我对这个问题的评论。)
  • 使用这个重写规则,你必须联合所有关系的两个连接(否则,你会得到一个错误的结果)。 IE。原始查询将是: SELECT * FROM R1, R2, R3, R4 WHERE (R1.A = '1' AND R4.D = '4') UNION SELECT * FROM R1, R2, R3, R4 (R2.B = '2' AND R3.C = R4.C AND R4.D = '4')在这种情况下,它不是优化(因此我在答案中声明了免责声明),但是在重写之后更容易看到查询求的是一系列笛卡尔积,所以没有太多可以优化的地方。
  • 你的评论只是重复了我的评论,所以我不知道你为什么写你的评论。此外,如果根据我在此处的评论,您阅读了我对问题的评论,那么您会发现可以通过将 ∨ 映射到选择/限制中的 ∨ 而不是 U. 像刚刚发布的正确答案 Christoph S 中的那样来优化开始查询。 (而不是他之前通过评论链接的不正确的那个。)
【解决方案2】:

联合是不可能的,因为它需要相同类型的列。 我现在从我的导师那里得到了一个官方的解决方案。 正如我已经想到的,需要使用分配规则将其转换为 KNF,以便我有两个子句单独的子句。

【讨论】:

    猜你喜欢
    • 2017-04-02
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多