【问题标题】:Complex SQL where clause: whether to factor logic复杂 SQL where 子句:是否分解逻辑
【发布时间】:2010-10-22 02:34:08
【问题描述】:

我有一个复杂的 SQL where 子句,由于需求更改而变得更加复杂。有四组基本案例,每组都有其他因素的不同组合。将四个案例作为 where 子句的单独分支,并在每个分支中重复冗余标准,这样更具可读性(在我看来)。但我不知道数据库引擎将如何优化它。

这是冗余形式的表达式。我已经用字母替换了实际标准。 A 是“分支”标准,有四种形式。除非另有说明,否则所有表达式均采用field='value' 的形式。

A1 AND B AND C AND D
OR A2 AND B AND C AND D AND E AND F1 AND G
OR A3 AND A3a AND B AND C AND D AND E AND F1 AND G
OR A4 AND B AND C AND D AND F2

除 A4 之外的所有 A 都采用 field in ('value1','value2') 的形式。 D 是field > 'value'。 G 的格式为field not in (subquery)

这是表达式,考虑到(我认为)它最不冗余的形式。

B AND C AND D AND (
    A1
    OR (
        E AND F1 AND G AND (
            A2
            OR (A3 AND A3a)
        )
    )
    OR (A4 AND F2)

我的问题是我是否应该将此表达式分解为最简单(最少冗余)的 逻辑 形式,或者是否可以将其保留为更冗余但更易读的形式。目标数据库是 Sybase,但我想知道一般 RDMBS 的答案。

【问题讨论】:

    标签: sql database optimization boolean boolean-logic


    【解决方案1】:

    RDBMS 的世界里,我不会过多地担心冗余,效率在这里更重要。

    在你的情况下,我会 UNION 使用 A 作为顶部条件的所有四个查询,如下所示:

    SELECT  *
    FROM    mytable
    WHERE   A1 AND B AND C
    UNION
    SELECT  *
    FROM    mytable
    WHERE   A2 AND B AND C AND D AND E AND F1 AND G
    …
    

    我对@9​​87654327@ 的研究没有超过7 年,但在所有主要的RDBMSUNION 上都比OR 的效率更高。

    请参阅我博客中的这篇文章,了解Oracle 中类似问题的解决方法:

    还有这篇文章用于比较UNIONOR 中的MySQL

    我认为这些方法也适用于Sybase

    您还需要在您的条件中使用的列上创建索引才能从UNION's 中受益

    更新:

    由于条件G 是一个子查询,它可能需要HASH JOIN 才能快速执行。 HASH JOIN 需要对所有未过滤的值进行全扫描,这就是为什么在一次全扫描中过滤所有值然后执行 HASH JOIN 可能会更好:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    foo
            WHERE   condition_set_1
            UNION
            SELECT  *
            FROM    foo
            WHERE   condition_set_2_but_no_g
            …
            ) q
    WHERE   G
    

    要做出进一步的判断,最好查看查询本身,真的。

    【讨论】:

    • 好建议。标准 G 使用子查询这一事实是否会降低 UNION 方法的效率(因为理论上它会发生在两个 SELECT 中),还是数据库引擎会优化这些类型的事情?
    • 对于G,需要查看查询本身才能做出判断。如果子查询很复杂,G 可能会扼杀分离的 UNION 查询中使用的索引的所有好处。也许全表扫描会更好。
    • 子查询逻辑简单,但是表很大。不过,子查询是在索引字段上进行选择,所以它可能不会太糟糕。我认为这种特殊情况是我必须尝试几种不同的方法,看看哪种方法最有效。
    【解决方案2】:

    如果我在 M$ SQL Server 上解决这个问题,我会按照我想要的方式编写它并查看查询执行计划。如果它 (a) 运行缓慢并且 (b) 有一个糟糕的执行计划,那么我会重构并记录。不确定 Sybase 中用于查看优化器如何执行查询的机制。

    【讨论】:

    • 感谢您的帖子。在 Sybase 中,您可以在运行查询之前运行 SET SHOWPLAN ON,它会显示详细信息(尽管是基于文本的格式,而不是像 SQL Server 那样的图形表示)
    【解决方案3】:

    我会重构它。最终,重复的逻辑会让你遇到问题。第二个示例可能需要几秒钟的时间才能理解,但在大范围内更容易看到发生了什么,因为您可以快速查看整个 where 子句并开始确定影响什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多