【问题标题】:SQL Query takes longer using With compared to subquery与子查询相比,使用 With 的 SQL 查询需要更长的时间
【发布时间】:2017-05-17 07:38:36
【问题描述】:

我有点困惑,为什么使用 with 子句的简单 SQL 查询比将它们放在子查询中花费的时间要长得多。我的 IDE 上超过 100 万条记录的实例使用 with 子句运行 > 30 分钟,使用子查询仅运行

下面只举一个简单的例子:

with table1 as (select tb1.a, tb1.b, tb2.c, tb3.d
                from tablea
                where a > 0 and b = 2016)
     table2 as (select a, b, c, d, e, f
                from table1 tb1
                left join table2 tb2 on tb1.a=tb2.a
                left join table3 tb3 on tb1.b=tb2.b)
select * from table2

与将它们作为子查询相比:

select * from (select a, b, c, d, e, f
                from (select tb1.a, tb1.b, tb2.c, tb3.d
                      from tablea
                      where a > 0 and b = 2016) tb1
                left join table2 tb2 on tb1.a=tb2.a
                left join table3 tb3 on tb1.b=tb2.b) table2

后者的查询完成速度比前者快得多。但是,前者在查询结构上更容易理解,所以如果可能的话,我更喜欢它。

不知道这个巨大的差异是由于我在解释时使用的IDE(DBeaver),还是基于SQL语句逻辑本身?

谢谢。

【问题讨论】:

  • 请提供两者的执行计划
  • 这被称为“postgresql 的优化围栏行为”。我确定它在 dba.stackexchange 上。
  • 顺便说一句,如果有人做这项工作,这可能会在 v11 中消失。黑客名单上的This lengthy thread 或多或少达成共识,取消它并引入MATERIALIZED 关键字,允许您明确选择旧行为。
  • @LaurenzAlbe 我已经关注了邮件列表上的讨论。恕我直言,更好的命名是 NOT MATERIALIZED ,因为标准 CTE 已经表现得好像物化了,尤其是在多次引用时。
  • 并非所有 CTE 都可以内联。对于那些不能,行为将保持不变。除非使用MATERIALIZED,否则新行为将尽可能内联。基本上,关键字的意思是“表现得像旧版本一样”,是一种查询提示。

标签: sql postgresql common-table-expression dbeaver


【解决方案1】:

这是因为在 Postgres 中,CTE 充当了优化障碍。一种解决方法(具有几乎相同的句法结构)是将 CTE 替换为 TEMP VIEWs :


CREATE TEMP VIEW v1 AS
        SELECT ta.a, ta.b, ta.c, ta.d
        FROM tablea ta
        WHERE a > 0 and b = 2016
        ;
CREATE TEMP VIEW v2 AS
        SELECT a, b, c, d, e, f
        FROM v1
        LEFT JOIN table2 tb2 ON v1.a=tb2.a
        LEFT JOIN table3 tb3 ON v1.b=tb3.b
        ;
SELECT * from v2;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多