优化 Postgres 中的 case/decode 查询

Posted

技术标签:

【中文标题】优化 Postgres 中的 case/decode 查询【英文标题】:Optimise case/decode query in Postgres 【发布时间】:2018-11-09 06:03:07 【问题描述】:

谁能帮助我以另一种方式实现以下查询?我面临性能问题,因为在多个 CASE 语句中到处都使用了相同的多个 SELECT 语句。

我的代码很大,这里有一大块:

        select col1,col2,
    ( CASE 
    WHEN NOT EXISTS (SELECT
                        CASE over.ola
                            WHEN NULL::text THEN 'NT'::character varying
                        END AS tover 
                    FROM   tsmt over 
                    WHERE  over.cod = hfprc.cod 
                            AND over.vdat = nav.vdat) THEN 'NT' 
    ELSE (SELECT CASE over.ola
                            WHEN NULL::text THEN 'TT'::character varying END
            FROM   tsmt over 
            WHERE  over.cod = hfprc.cod 
                AND over.vdat = nav.vdat) 
    END )
        olaflag, 
    (SELECT description 
    FROM   tolahfp tover 
    WHERE  tover.ola = (SELECT CASE 
                                    WHEN NOT EXISTS (SELECT
                                        CASE over.ola
    WHEN NULL::text THEN 'TT'::character varying
                                        END AS 
            tover 
                    FROM   tsmt over 
                    WHERE  over.cod = hfprc.cod 
                        AND over.vdat = nav.vdat) THEN 'TT' 
            ELSE (SELECT CASE over.ola
    WHEN NULL::text THEN 'TT'::character varying
                                        END AS tover 
            FROM   tsmt over 
            WHERE  over.cod = hfprc.cod 
                AND over.vdat = nav.vdat) 
            END ola 
        )) 
        ola,--ola description 

        (CASE thfp.codcag::text
                WHEN NULL::text THEN 'CCCC'::character varying
            END 
        )codcag, 
    (SELECT conf.descag 
    FROM   thfconagrhfp conf 
    WHERE  conf.codcag = CASE thfp.codcag::text
                        WHEN NULL::text THEN 'CCCC'::character varying
                    END) 
        desccag, 
    thfp.frq, 
    thfp.flgcal 
    FROM   thpr hfprc LEFT JOIN tgrpprchfp grp ON hfprc.cgrp = grp.cgrp 

        LEFT JOIN tnav nav ON hfprc.cod = nav.cod AND nav.flag = 'Y' 
        LEFT JOIN thf thfp ON  hfprc.cod = thfp.cod
        LEFT JOIN tsmtdatthdhfp smtdatthd ON hfprc.cod = smtdatthd.cod

【问题讨论】:

【参考方案1】:

您是否使用sqlsmith 编写查询?

但是,更严重的是,这里的前进方式是用外连接替换子选择。

举个例子:

SELECT CASE WHEN NOT EXISTS (SELECT weirdfunc(x.x1)
                             FROM x
                             WHERE x.x2 = y.y2
                               AND x.x3 = z.z3)
            THEN 'Constant'
            ELSE (SELECT otherweirdfunc(x.x1)
                  FROM x
                  WHERE x.x2 = y.y2
                    AND x.x3 = z.z3)
       END
FROM y
   LEFT JOIN z USING (t);

写成这样会更好更高效

SELECT coalesce(otherweirdfunc(x.x1), 'Constant')
FROM y
   LEFT JOIN z USING (t)
   LEFT JOIN x ON x.x2 = y.y2 AND x.x3 = z.z3;

我的经验法则是:除了FROM 子句之外,子选择通常在任何地方都是错误的。

【讨论】:

不知道 sqlsmith 用于此目的,我刚刚将此查询从 oracle 迁移到 postgres 最后已经使用了外连接!!!我怎样才能消除在我的代码中多次使用相同的查询? 那是我给你看的,不是吗?我简化了您的部分查询以显示原理。 sqlsmith 参考只是一个玩笑。

以上是关于优化 Postgres 中的 case/decode 查询的主要内容,如果未能解决你的问题,请参考以下文章

最佳实践:优化Postgres查询性能(下)

最佳实践:优化Postgres查询性能(下)

优化 postgres 数据库和查询的不同步骤是啥?

您所不了解的Postgres 10功能:CREATE STATISTICS(译)

Postgres:按日期时间优化查询

如何优化这个 Postgres 查询?