or等价改写union SQL案例

同事找我优化一些SQL,其中有个SQL比较经典,拿出来分享给大家,从原来执行2分钟,到1.4S出结果。

-- 原SQL 
SELECT
    count (*)
FROM (
        SELECT
            DISTINCT T1.id,
            T1.doc_no,
            T1.title,
            T1.type,
            T1.addTime,
            T1.urgency,
            T1.addUser,
            T1.fileNo,
            T1.fileNoID,
            T1.orgId,
            T1.deptId,
            T1.fromDept,
            T1.docType,
            T1.docTypeID,
            T1.isOld,
            T1.publicState,
            T1.oaPublicState,
            P.state AS activeState,
            P.cate_id AS cateID,
            P.id AS procInsID
        FROM
            A T1,
            B P
        WHERE
            T1.id = P.case_id
            AND T1.addTime >= '2021-11-17 00:00:00'
            AND T1.addTime <= '2022-11-17 23:59:59'
            AND T1.type IN ('receive', 'dispatch', 'draft')
            AND (T1.oapublicstate = '1'
                OR EXISTS (
                    SELECT
                        P.case_id AS wf_case_id
                    FROM
                        wf_proc_ins_handlers H
                    WHERE
                        P.id = H.proc_ins_id
                        AND H.handler_id = '704fa12e-0166-1000-e000-05a00a010169'))) x;

 这个节点循环了 47108 次,这个节点所需要的时间计算为 47108 * 2.695 = 126,956.06ms  ,2分钟,影响了整条SQL的执行时间。

对应的SQL语句是这段

 

这种语句使用OR 加任何索引都不好使,想要优化只能改写改SQL。

-- 改写SQL优化

with x as (
        SELECT
            DISTINCT T1.id,
            T1.doc_no,
            T1.title,
            T1.type,
            T1.addTime,
            T1.urgency,
            T1.addUser,
            T1.fileNo,
            T1.fileNoID,
            T1.orgId,
            T1.deptId,
            T1.fromDept,
            T1.docType,
            T1.docTypeID,
            T1.isOld,
            T1.publicState,
            T1.oaPublicState,
            P.state AS activeState,
            P.cate_id AS cateID,
            P.id AS procInsID
        FROM
            A T1,
            B P
        WHERE
            T1.id = P.case_id
            AND T1.addTime >= '2021-11-17 00:00:00'
            AND T1.addTime <= '2022-11-17 23:59:59'
            AND T1.type IN ('receive', 'dispatch', 'draft')

)
select count(*) from (
select x1.* from x x1 where x1.oapublicstate = '1'
union 
select x2.* from x x2 left join wf_proc_ins_handlers h on x2.procInsID = h.proc_ins_id where  h.handler_id = '704fa12e-0166-1000-e000-05a00a010169' and h.proc_ins_id is not null
);

 

 

SQL 执行计划

 

   修改之后只需要1.4S 就能出结果,两条语句比较 count(*) 结果集等价。

posted @ 2022-11-18 16:07  小至尖尖  阅读(179)  评论(0编辑  收藏  举报