postgresql 标量子查询改写的各种姿势

同事提供一条SQL,原执行时间需要 3.6S ,反馈比较慢需要优化一下,废话不说贴SQL:

原SQL:

select ((select count(1)
         FROM AAAAAAAAA wf
                   join BBBBBBBBBB procinst on procinst.id_ = wf.proc_inst_id
                  join ccccccccc xpc on xpc.id = wf.master_entity_key
                  join (select procinst_, max(duedate) as expire_date from DDDDDDDDD group by procinst_) t_expire
                       on t_expire.procinst_ = wf.proc_inst_id
         where procinst.state_ in ('active')
           and wf.master_entity = 'ccccccccc'
           and xpc.project_sort = 'XM_PROJECT_SPECIAL'
           and wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_)) + (select count(1)
                                                                                           FROM AAAAAAAAA wf
                                                                                                    join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                                                                                                    join (select procinst_, max(duedate) as expire_date
                                                                                                          from DDDDDDDDD
                                                                                                          group by procinst_) t_expire
                                                                                                          on t_expire.procinst_ = wf.proc_inst_id

                                                                                           where procinst.state_ in ('active')
                                                                                             and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                                                                                             and wf.bus_num1 <=
                                                                                                 date_part('day', t_expire.expire_date - procinst.start_))) as ZB,
        ((select count(1)
         FROM AAAAAAAAA wf
                  join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                   join ccccccccc xpc on xpc.id = wf.master_entity_key
                  join (select procinst_, max(duedate) as expire_date from DDDDDDDDD group by procinst_) t_expire
                       on t_expire.procinst_ = wf.proc_inst_id
         where procinst.state_ in ('ended')
           and wf.master_entity = 'ccccccccc'
           and xpc.project_sort = 'XM_PROJECT_SPECIAL'
            and wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_)) + (select count(1)
                                                                                           FROM AAAAAAAAA wf
                                                                                                    join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                                                                                                    join (select procinst_, max(duedate) as expire_date
                                                                                                          from DDDDDDDDD
                                                                                                          group by procinst_) t_expire
                                                                                                         on t_expire.procinst_ = wf.proc_inst_id
                                                                                           where procinst.state_ in ('ended')
                                                                                             and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                                                                                             and wf.bus_num1 <=
                                                                                                 date_part('day', t_expire.expire_date - procinst.start_))) as BJ,
       ((select count(1)
         FROM AAAAAAAAA wf
                  join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                  join ccccccccc xpc on xpc.id = wf.master_entity_key
                  join (select procinst_, max(duedate) as expire_date from DDDDDDDDD group by procinst_) t_expire
                       on t_expire.procinst_ = wf.proc_inst_id
         where procinst.state_ in ('active')
           and wf.master_entity = 'ccccccccc'
           and xpc.project_sort = 'XM_PROJECT_SPECIAL'
           and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_)) + (select count(1)
                                                                                          FROM AAAAAAAAA wf
                                                                                                   join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                                                                                                   join (select procinst_, max(duedate) as expire_date
                                                                                                         from DDDDDDDDD
                                                                                                         group by procinst_) t_expire
                                                                                                        on t_expire.procinst_ = wf.proc_inst_id
                                                                                          where procinst.state_ in ('active')
                                                                                            and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                                                                                            and wf.bus_num1 >
                                                                                                date_part('day', t_expire.expire_date - procinst.start_)))  as YQZB,
       ((select count(1)
         FROM AAAAAAAAA wf
                  join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                  join ccccccccc xpc on xpc.id = wf.master_entity_key
                  join (select procinst_, max(duedate) as expire_date from DDDDDDDDD group by procinst_) t_expire
                       on t_expire.procinst_ = wf.proc_inst_id
         where procinst.state_ in ('ended')
           and wf.master_entity = 'ccccccccc'
           and xpc.project_sort = 'XM_PROJECT_SPECIAL'
           and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_)) + (select count(1)
                                                                                          FROM AAAAAAAAA wf
                                                                                                   join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
                                                                                                   join (select procinst_, max(duedate) as expire_date
                                                                                                         from DDDDDDDDD
                                                                                                         group by procinst_) t_expire
                                                                                                        on t_expire.procinst_ = wf.proc_inst_id
                                                                                          where procinst.state_ in ('ended')
                                                                                            and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                                                                                            and wf.bus_num1 >
                                                                                                date_part('day', t_expire.expire_date - procinst.start_)))  as YQBJ;


 ZB | BJ  | YQZB | YQBJ 
----+-----+------+------
  0 | 154 |   12 |  128
(1 row)

 

执行计划:

                                                                                                  QUERY PLAN                                                                                                   
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Result  (cost=705941.01..705941.03 rows=1 width=32) (actual time=3607.065..3607.101 rows=1 loops=1)
   InitPlan 1 (returns $1)
     ->  Aggregate  (cost=89551.78..89551.79 rows=1 width=8) (actual time=459.571..459.578 rows=1 loops=1)
           ->  Nested Loop  (cost=87092.97..89551.77 rows=2 width=0) (actual time=459.568..459.573 rows=0 loops=1)
                 Join Filter: (((wf.proc_inst_id)::text = (procinst.id_)::text) AND ((wf.bus_num1)::double precision <= date_part('day'::text, ((max(DDDDDDDDD.duedate)) - procinst.start_))))
                 Rows Removed by Join Filter: 7
                 ->  Hash Join  (cost=87092.69..89543.65 rows=18 width=65) (actual time=458.089..458.846 rows=99 loops=1)
                       Hash Cond: ((wf.proc_inst_id)::text = (DDDDDDDDD.procinst_)::text)
                       ->  Hash Join  (cost=1955.82..4406.74 rows=20 width=31) (actual time=33.853..34.568 rows=99 loops=1)
                             Hash Cond: (wf.master_entity_key = xpc.id)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf  (cost=1898.14..4347.12 rows=740 width=36) (actual time=33.408..34.156 rows=740 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'ccccccccc'::text)
                                   Heap Blocks: exact=116
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..1897.96 rows=740 width=0) (actual time=8.348..8.348 rows=103217 loops=1)
                                         Index Cond: ((master_entity)::text = 'ccccccccc'::text)
                             ->  Hash  (cost=56.38..56.38 rows=104 width=5) (actual time=0.164..0.165 rows=100 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 12kB
                                   ->  Bitmap Heap Scan on ccccccccc xpc  (cost=5.08..56.38 rows=104 width=5) (actual time=0.040..0.134 rows=100 loops=1)
                                         Recheck Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                                         Heap Blocks: exact=32
                                         ->  Bitmap Index Scan on ccccccccc_project_sort_idx  (cost=0.00..5.06 rows=104 width=0) (actual time=0.025..0.025 rows=100 loops=1)
                                               Index Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                       ->  Hash  (cost=85076.48..85076.48 rows=4831 width=34) (actual time=424.217..424.217 rows=5333 loops=1)
                             Buckets: 8192  Batches: 1  Memory Usage: 419kB
                             ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=421.887..422.887 rows=5333 loops=1)
                                   Group Key: DDDDDDDDD.procinst_
                                   ->  Seq Scan on DDDDDDDDD  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.012..383.892 rows=52257 loops=1)
                 ->  Index Scan using idx_getsummy_p on EEEEEEEEEEE procinst  (cost=0.28..0.43 rows=1 width=34) (actual time=0.007..0.007 rows=0 loops=99)
                       Index Cond: (((id_)::text = (DDDDDDDDD.procinst_)::text) AND ((state_)::text = 'active'::text))
   InitPlan 2 (returns $2)
     ->  Aggregate  (cost=86930.57..86930.58 rows=1 width=8) (actual time=442.198..442.202 rows=1 loops=1)
           ->  Hash Join  (cost=86814.21..86930.51 rows=26 width=0) (actual time=442.196..442.199 rows=0 loops=1)
                 Hash Cond: ((DDDDDDDDD_1.procinst_)::text = (procinst_1.id_)::text)
                 Join Filter: ((wf_1.bus_num1)::double precision <= date_part('day'::text, ((max(DDDDDDDDD_1.duedate)) - procinst_1.start_)))
                 Rows Removed by Join Filter: 33
                 ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=423.106..424.110 rows=5333 loops=1)
                       Group Key: DDDDDDDDD_1.procinst_
                       ->  Seq Scan on DDDDDDDDD DDDDDDDDD_1  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.012..384.952 rows=52257 loops=1)
                 ->  Hash  (cost=1833.28..1833.28 rows=86 width=65) (actual time=17.369..17.371 rows=33 loops=1)
                       Buckets: 1024  Batches: 1  Memory Usage: 12kB
                       ->  Hash Join  (cost=869.12..1833.28 rows=86 width=65) (actual time=17.066..17.357 rows=33 loops=1)
                             Hash Cond: ((wf_1.proc_inst_id)::text = (procinst_1.id_)::text)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf_1  (cost=686.48..1648.78 rows=267 width=31) (actual time=3.750..15.724 rows=267 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                                   Heap Blocks: exact=91
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..686.41 rows=267 width=0) (actual time=3.194..3.194 rows=36061 loops=1)
                                         Index Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                             ->  Hash  (cost=161.13..161.13 rows=1721 width=34) (actual time=1.542..1.543 rows=1722 loops=1)
                                   Buckets: 2048  Batches: 1  Memory Usage: 131kB
                                   ->  Bitmap Heap Scan on EEEEEEEEEEE procinst_1  (cost=37.62..161.13 rows=1721 width=34) (actual time=0.172..1.108 rows=1722 loops=1)
                                         Recheck Cond: ((state_)::text = 'active'::text)
                                         Heap Blocks: exact=97
                                         ->  Bitmap Index Scan on EEEEEEEEEEE_state__idx  (cost=0.00..37.19 rows=1721 width=0) (actual time=0.157..0.157 rows=1844 loops=1)
                                               Index Cond: ((state_)::text = 'active'::text)
   InitPlan 3 (returns $4)
     ->  Aggregate  (cost=89551.78..89551.79 rows=1 width=8) (actual time=460.928..460.932 rows=1 loops=1)
           ->  Nested Loop  (cost=87092.97..89551.77 rows=4 width=0) (actual time=459.326..460.925 rows=19 loops=1)
                 Join Filter: (((wf_2.proc_inst_id)::text = (procinst_2.id_)::text) AND ((wf_2.bus_num1)::double precision <= date_part('day'::text, ((max(DDDDDDDDD_2.duedate)) - procinst_2.start_))))
                 Rows Removed by Join Filter: 73
                 ->  Hash Join  (cost=87092.69..89543.65 rows=18 width=65) (actual time=459.162..459.959 rows=99 loops=1)
                       Hash Cond: ((wf_2.proc_inst_id)::text = (DDDDDDDDD_2.procinst_)::text)
                       ->  Hash Join  (cost=1955.82..4406.74 rows=20 width=31) (actual time=33.042..33.798 rows=99 loops=1)
                             Hash Cond: (wf_2.master_entity_key = xpc_1.id)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf_2  (cost=1898.14..4347.12 rows=740 width=36) (actual time=32.584..33.382 rows=740 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'ccccccccc'::text)
                                   Heap Blocks: exact=116
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..1897.96 rows=740 width=0) (actual time=8.245..8.245 rows=103217 loops=1)
                                         Index Cond: ((master_entity)::text = 'ccccccccc'::text)
                             ->  Hash  (cost=56.38..56.38 rows=104 width=5) (actual time=0.167..0.168 rows=100 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 12kB
                                   ->  Bitmap Heap Scan on ccccccccc xpc_1  (cost=5.08..56.38 rows=104 width=5) (actual time=0.051..0.140 rows=100 loops=1)
                                         Recheck Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                                         Heap Blocks: exact=32
                                         ->  Bitmap Index Scan on ccccccccc_project_sort_idx  (cost=0.00..5.06 rows=104 width=0) (actual time=0.036..0.036 rows=100 loops=1)
                                               Index Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                       ->  Hash  (cost=85076.48..85076.48 rows=4831 width=34) (actual time=426.103..426.104 rows=5333 loops=1)
                             Buckets: 8192  Batches: 1  Memory Usage: 419kB
                             ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=423.767..424.766 rows=5333 loops=1)
                                   Group Key: DDDDDDDDD_2.procinst_
                                   ->  Seq Scan on DDDDDDDDD DDDDDDDDD_2  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.013..385.665 rows=52257 loops=1)
                 ->  Index Scan using idx_getsummy_p on EEEEEEEEEEE procinst_2  (cost=0.28..0.43 rows=1 width=34) (actual time=0.008..0.009 rows=1 loops=99)
                       Index Cond: (((id_)::text = (DDDDDDDDD_2.procinst_)::text) AND ((state_)::text = 'ended'::text))
   InitPlan 4 (returns $5)
     ->  Aggregate  (cost=86936.34..86936.35 rows=1 width=8) (actual time=440.862..440.865 rows=1 loops=1)
           ->  Hash Join  (cost=86818.27..86936.20 rows=53 width=0) (actual time=438.978..440.848 rows=135 loops=1)
                 Hash Cond: ((DDDDDDDDD_3.procinst_)::text = (procinst_3.id_)::text)
                 Join Filter: ((wf_3.bus_num1)::double precision <= date_part('day'::text, ((max(DDDDDDDDD_3.duedate)) - procinst_3.start_)))
                 Rows Removed by Join Filter: 88
                 ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=420.198..421.209 rows=5333 loops=1)
                       Group Key: DDDDDDDDD_3.procinst_
                       ->  Seq Scan on DDDDDDDDD DDDDDDDDD_3  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.009..382.419 rows=52257 loops=1)
                 ->  Hash  (cost=1836.20..1836.20 rows=177 width=65) (actual time=18.737..18.739 rows=223 loops=1)
                       Buckets: 1024  Batches: 1  Memory Usage: 31kB
                       ->  Hash Join  (cost=1652.11..1836.20 rows=177 width=65) (actual time=16.697..18.674 rows=223 loops=1)
                             Hash Cond: ((procinst_3.id_)::text = (wf_3.proc_inst_id)::text)
                             ->  Seq Scan on EEEEEEEEEEE procinst_3  (cost=0.00..168.98 rows=3558 width=34) (actual time=0.015..1.949 rows=3545 loops=1)
                                   Filter: ((state_)::text = 'ended'::text)
                                   Rows Removed by Filter: 1816
                             ->  Hash  (cost=1648.78..1648.78 rows=267 width=31) (actual time=16.211..16.212 rows=267 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 25kB
                                   ->  Bitmap Heap Scan on AAAAAAAAA wf_3  (cost=686.48..1648.78 rows=267 width=31) (actual time=3.778..16.142 rows=267 loops=1)
                                         Recheck Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                                         Heap Blocks: exact=91
                                         ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..686.41 rows=267 width=0) (actual time=3.214..3.214 rows=36061 loops=1)
                                               Index Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
   InitPlan 5 (returns $7)
     ->  Aggregate  (cost=89551.78..89551.79 rows=1 width=8) (actual time=453.867..453.872 rows=1 loops=1)
           ->  Nested Loop  (cost=87092.97..89551.77 rows=2 width=0) (actual time=453.766..453.866 rows=1 loops=1)
                 Join Filter: (((wf_4.proc_inst_id)::text = (procinst_4.id_)::text) AND ((wf_4.bus_num1)::double precision > date_part('day'::text, ((max(DDDDDDDDD_4.duedate)) - procinst_4.start_))))
                 Rows Removed by Join Filter: 6
                 ->  Hash Join  (cost=87092.69..89543.65 rows=18 width=65) (actual time=452.410..453.150 rows=99 loops=1)
                       Hash Cond: ((wf_4.proc_inst_id)::text = (DDDDDDDDD_4.procinst_)::text)
                       ->  Hash Join  (cost=1955.82..4406.74 rows=20 width=31) (actual time=32.643..33.343 rows=99 loops=1)
                             Hash Cond: (wf_4.master_entity_key = xpc_2.id)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf_4  (cost=1898.14..4347.12 rows=740 width=36) (actual time=32.192..32.932 rows=740 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'ccccccccc'::text)
                                   Heap Blocks: exact=116
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..1897.96 rows=740 width=0) (actual time=8.285..8.285 rows=103217 loops=1)
                                         Index Cond: ((master_entity)::text = 'ccccccccc'::text)
                             ->  Hash  (cost=56.38..56.38 rows=104 width=5) (actual time=0.165..0.166 rows=100 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 12kB
                                   ->  Bitmap Heap Scan on ccccccccc xpc_2  (cost=5.08..56.38 rows=104 width=5) (actual time=0.051..0.137 rows=100 loops=1)
                                         Recheck Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                                         Heap Blocks: exact=32
                                         ->  Bitmap Index Scan on ccccccccc_project_sort_idx  (cost=0.00..5.06 rows=104 width=0) (actual time=0.035..0.036 rows=100 loops=1)
                                               Index Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                       ->  Hash  (cost=85076.48..85076.48 rows=4831 width=34) (actual time=419.751..419.752 rows=5333 loops=1)
                             Buckets: 8192  Batches: 1  Memory Usage: 419kB
                             ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=417.422..418.416 rows=5333 loops=1)
                                   Group Key: DDDDDDDDD_4.procinst_
                                   ->  Seq Scan on DDDDDDDDD DDDDDDDDD_4  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.011..379.472 rows=52257 loops=1)
                 ->  Index Scan using idx_getsummy_p on EEEEEEEEEEE procinst_4  (cost=0.28..0.43 rows=1 width=34) (actual time=0.007..0.007 rows=0 loops=99)
                       Index Cond: (((id_)::text = (DDDDDDDDD_4.procinst_)::text) AND ((state_)::text = 'active'::text))
   InitPlan 6 (returns $8)
     ->  Aggregate  (cost=86930.57..86930.58 rows=1 width=8) (actual time=443.903..443.908 rows=1 loops=1)
           ->  Hash Join  (cost=86814.21..86930.51 rows=26 width=0) (actual time=442.221..443.900 rows=11 loops=1)
                 Hash Cond: ((DDDDDDDDD_5.procinst_)::text = (procinst_5.id_)::text)
                 Join Filter: ((wf_5.bus_num1)::double precision > date_part('day'::text, ((max(DDDDDDDDD_5.duedate)) - procinst_5.start_)))
                 Rows Removed by Join Filter: 22
                 ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=424.690..425.691 rows=5333 loops=1)
                       Group Key: DDDDDDDDD_5.procinst_
                       ->  Seq Scan on DDDDDDDDD DDDDDDDDD_5  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.011..386.627 rows=52257 loops=1)
                 ->  Hash  (cost=1833.28..1833.28 rows=86 width=65) (actual time=17.483..17.485 rows=33 loops=1)
                       Buckets: 1024  Batches: 1  Memory Usage: 12kB
                       ->  Hash Join  (cost=869.12..1833.28 rows=86 width=65) (actual time=17.183..17.472 rows=33 loops=1)
                             Hash Cond: ((wf_5.proc_inst_id)::text = (procinst_5.id_)::text)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf_5  (cost=686.48..1648.78 rows=267 width=31) (actual time=3.671..15.869 rows=267 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                                   Heap Blocks: exact=91
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..686.41 rows=267 width=0) (actual time=3.107..3.107 rows=36061 loops=1)
                                         Index Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                             ->  Hash  (cost=161.13..161.13 rows=1721 width=34) (actual time=1.513..1.514 rows=1722 loops=1)
                                   Buckets: 2048  Batches: 1  Memory Usage: 131kB
                                   ->  Bitmap Heap Scan on EEEEEEEEEEE procinst_5  (cost=37.62..161.13 rows=1721 width=34) (actual time=0.150..1.090 rows=1722 loops=1)
                                         Recheck Cond: ((state_)::text = 'active'::text)
                                         Heap Blocks: exact=97
                                         ->  Bitmap Index Scan on EEEEEEEEEEE_state__idx  (cost=0.00..37.19 rows=1721 width=0) (actual time=0.136..0.136 rows=1844 loops=1)
                                               Index Cond: ((state_)::text = 'active'::text)
   InitPlan 7 (returns $10)
     ->  Aggregate  (cost=89551.78..89551.79 rows=1 width=8) (actual time=462.657..462.661 rows=1 loops=1)
           ->  Nested Loop  (cost=87092.97..89551.77 rows=4 width=0) (actual time=461.038..462.652 rows=40 loops=1)
                 Join Filter: (((wf_6.proc_inst_id)::text = (procinst_6.id_)::text) AND ((wf_6.bus_num1)::double precision > date_part('day'::text, ((max(DDDDDDDDD_6.duedate)) - procinst_6.start_))))
                 Rows Removed by Join Filter: 52
                 ->  Hash Join  (cost=87092.69..89543.65 rows=18 width=65) (actual time=460.961..461.725 rows=99 loops=1)
                       Hash Cond: ((wf_6.proc_inst_id)::text = (DDDDDDDDD_6.procinst_)::text)
                       ->  Hash Join  (cost=1955.82..4406.74 rows=20 width=31) (actual time=33.547..34.270 rows=99 loops=1)
                             Hash Cond: (wf_6.master_entity_key = xpc_3.id)
                             ->  Bitmap Heap Scan on AAAAAAAAA wf_6  (cost=1898.14..4347.12 rows=740 width=36) (actual time=33.096..33.861 rows=740 loops=1)
                                   Recheck Cond: ((master_entity)::text = 'ccccccccc'::text)
                                   Heap Blocks: exact=116
                                   ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..1897.96 rows=740 width=0) (actual time=8.462..8.462 rows=103217 loops=1)
                                         Index Cond: ((master_entity)::text = 'ccccccccc'::text)
                             ->  Hash  (cost=56.38..56.38 rows=104 width=5) (actual time=0.162..0.163 rows=100 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 12kB
                                   ->  Bitmap Heap Scan on ccccccccc xpc_3  (cost=5.08..56.38 rows=104 width=5) (actual time=0.048..0.134 rows=100 loops=1)
                                         Recheck Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                                         Heap Blocks: exact=32
                                         ->  Bitmap Index Scan on ccccccccc_project_sort_idx  (cost=0.00..5.06 rows=104 width=0) (actual time=0.034..0.035 rows=100 loops=1)
                                               Index Cond: ((project_sort)::text = 'XM_PROJECT_SPECIAL'::text)
                       ->  Hash  (cost=85076.48..85076.48 rows=4831 width=34) (actual time=427.397..427.398 rows=5333 loops=1)
                             Buckets: 8192  Batches: 1  Memory Usage: 419kB
                             ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=425.069..426.072 rows=5333 loops=1)
                                   Group Key: DDDDDDDDD_6.procinst_
                                   ->  Seq Scan on DDDDDDDDD DDDDDDDDD_6  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.012..387.173 rows=52257 loops=1)
                 ->  Index Scan using idx_getsummy_p on EEEEEEEEEEE procinst_6  (cost=0.28..0.43 rows=1 width=34) (actual time=0.008..0.008 rows=1 loops=99)
                       Index Cond: (((id_)::text = (DDDDDDDDD_6.procinst_)::text) AND ((state_)::text = 'ended'::text))
   InitPlan 8 (returns $11)
     ->  Aggregate  (cost=86936.34..86936.35 rows=1 width=8) (actual time=443.046..443.048 rows=1 loops=1)
           ->  Hash Join  (cost=86818.27..86936.20 rows=53 width=0) (actual time=441.214..443.036 rows=88 loops=1)
                 Hash Cond: ((DDDDDDDDD_7.procinst_)::text = (procinst_7.id_)::text)
                 Join Filter: ((wf_7.bus_num1)::double precision > date_part('day'::text, ((max(DDDDDDDDD_7.duedate)) - procinst_7.start_)))
                 Rows Removed by Join Filter: 135
                 ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=422.761..423.762 rows=5333 loops=1)
                       Group Key: DDDDDDDDD_7.procinst_
                       ->  Seq Scan on DDDDDDDDD DDDDDDDDD_7  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.015..384.640 rows=52257 loops=1)
                 ->  Hash  (cost=1836.20..1836.20 rows=177 width=65) (actual time=18.421..18.423 rows=223 loops=1)
                       Buckets: 1024  Batches: 1  Memory Usage: 31kB
                       ->  Hash Join  (cost=1652.11..1836.20 rows=177 width=65) (actual time=16.255..18.355 rows=223 loops=1)
                             Hash Cond: ((procinst_7.id_)::text = (wf_7.proc_inst_id)::text)
                             ->  Seq Scan on EEEEEEEEEEE procinst_7  (cost=0.00..168.98 rows=3558 width=34) (actual time=0.012..2.104 rows=3545 loops=1)
                                   Filter: ((state_)::text = 'ended'::text)
                                   Rows Removed by Filter: 1816
                             ->  Hash  (cost=1648.78..1648.78 rows=267 width=31) (actual time=15.740..15.741 rows=267 loops=1)
                                   Buckets: 1024  Batches: 1  Memory Usage: 25kB
                                   ->  Bitmap Heap Scan on AAAAAAAAA wf_7  (cost=686.48..1648.78 rows=267 width=31) (actual time=3.740..15.669 rows=267 loops=1)
                                         Recheck Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                                         Heap Blocks: exact=91
                                         ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..686.41 rows=267 width=0) (actual time=3.180..3.180 rows=36061 loops=1)
                                               Index Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
 Planning Time: 5.092 ms
 Execution Time: 3607.579 ms
(211 rows)

这条 SQL 属于标量子查询,最终结果返回一行,输出结果 4个字段,

每个字段包含两个表达式聚合结果相加,过滤条件略有不同,共8个SQL表达式,

从执行计划可以看到 InitPlan 1-8。

等价改写方式1:

select (
               count((case
                          when procinst.state_ in ('active') and wf.master_entity = 'ccccccccc' and
                               xpc.project_sort = 'XM_PROJECT_SPECIAL' and
                               wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
               +
               count((case
                          when procinst.state_ in ('active') and wf.master_entity = 'REGULATORY_PLAN_STAGE' and
                               wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
            ) as ZB,

       (
               count((case
                          when procinst.state_ in ('ended') and wf.master_entity = 'ccccccccc' and
                               xpc.project_sort = 'XM_PROJECT_SPECIAL' and
                               wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
               +
               count((case
                          when procinst.state_ in ('ended') and wf.master_entity = 'REGULATORY_PLAN_STAGE' and
                               wf.bus_num1 <= date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
            ) as BJ,

       (
               count((case
                          when procinst.state_ in ('active')
                              and wf.master_entity = 'ccccccccc'
                              and xpc.project_sort = 'XM_PROJECT_SPECIAL'
                              and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
               +
               count((case
                          when procinst.state_ in ('active')
                              and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                              and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
           )                               as YQBJ,

       (
               count((case
                          when procinst.state_ in ('ended')
                              and wf.master_entity = 'ccccccccc'
                              and xpc.project_sort = 'XM_PROJECT_SPECIAL'
                              and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
               +
               count((case
                          when procinst.state_ in ('ended')
                              and wf.master_entity = 'REGULATORY_PLAN_STAGE'
                              and wf.bus_num1 > date_part('day', t_expire.expire_date - procinst.start_) then '1'
                          else null end))
           )                               as YQZB
FROM AAAAAAAAA wf
       left join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id
       left join ccccccccc xpc on xpc.id = wf.master_entity_key
       left join (select procinst_, max(duedate) as expire_date from DDDDDDDDD group by procinst_) t_expire
              on t_expire.procinst_ = wf.proc_inst_id
where procinst.state_ in ('active', 'ended')
    and (wf.master_entity = 'ccccccccc' and xpc.project_sort = 'XM_PROJECT_SPECIAL')
   or wf.master_entity = 'REGULATORY_PLAN_STAGE';


 ZB | BJ  | YQZB | YQBJ 
----+-----+------+------
  0 | 154 |   12 |  128

 

执行计划1:

                                                                                                                                 QUERY PLAN                                                                                        
                                         
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=91247.69..91247.71 rows=1 width=32) (actual time=461.756..461.763 rows=1 loops=1)
   ->  Hash Left Join  (cost=88010.99..91237.79 rows=66 width=63) (actual time=430.033..461.264 rows=366 loops=1)
         Hash Cond: ((wf.proc_inst_id)::text = (t_expire.procinst_)::text)
         ->  Hash Left Join  (cost=2874.12..6100.76 rows=66 width=81) (actual time=16.241..47.265 rows=366 loops=1)
               Hash Cond: (wf.master_entity_key = xpc.id)
               Filter: ((((procinst.state_)::text = ANY ('{active,ended}'::text[])) AND ((wf.master_entity)::text = 'ccccccccc'::text) AND ((xpc.project_sort)::text = 'XM_PROJECT_SPECIAL'::text)) OR ((wf.master_entity)::text = 'REGULATORY_PLAN_STAGE'::text))
               Rows Removed by Filter: 641
               ->  Hash Left Join  (cost=2807.41..6031.50 rows=970 width=68) (actual time=15.403..45.825 rows=1007 loops=1)
                     Hash Cond: ((wf.proc_inst_id)::text = (procinst.id_)::text)
                     ->  Bitmap Heap Scan on AAAAAAAAA wf  (cost=2584.85..5795.60 rows=970 width=54) (actual time=12.446..42.095 rows=1007 loops=1)
                           Recheck Cond: (((master_entity)::text = 'ccccccccc'::text) OR ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text))
                           Heap Blocks: exact=118
                           ->  BitmapOr  (cost=2584.85..2584.85 rows=1007 width=0) (actual time=11.330..11.331 rows=0 loops=1)
                                 ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..1897.96 rows=740 width=0) (actual time=8.208..8.208 rows=103217 loops=1)
                                       Index Cond: ((master_entity)::text = 'ccccccccc'::text)
                                 ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..686.41 rows=267 width=0) (actual time=3.121..3.122 rows=36061 loops=1)
                                       Index Cond: ((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text)
                     ->  Hash  (cost=155.58..155.58 rows=5358 width=40) (actual time=2.944..2.945 rows=5361 loops=1)
                           Buckets: 8192  Batches: 1  Memory Usage: 456kB
                           ->  Seq Scan on EEEEEEEEEEE procinst  (cost=0.00..155.58 rows=5358 width=40) (actual time=0.017..1.452 rows=5361 loops=1)
               ->  Hash  (cost=57.43..57.43 rows=743 width=23) (actual time=0.829..0.829 rows=743 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 49kB
                     ->  Seq Scan on ccccccccc xpc  (cost=0.00..57.43 rows=743 width=23) (actual time=0.006..0.620 rows=743 loops=1)
         ->  Hash  (cost=85076.48..85076.48 rows=4831 width=34) (actual time=413.781..413.782 rows=5333 loops=1)
               Buckets: 8192  Batches: 1  Memory Usage: 403kB
               ->  Subquery Scan on t_expire  (cost=84979.86..85076.48 rows=4831 width=34) (actual time=410.613..412.370 rows=5333 loops=1)
                     ->  HashAggregate  (cost=84979.86..85028.17 rows=4831 width=34) (actual time=410.611..411.793 rows=5333 loops=1)
                           Group Key: DDDDDDDDD.procinst_
                           ->  Seq Scan on DDDDDDDDD  (cost=0.00..84718.57 rows=52257 width=34) (actual time=0.008..371.865 rows=52257 loops=1)
 Planning Time: 0.805 ms
 Execution Time: 461.907 ms
(31 rows)

改写后可以看到只需要 461ms 就能把结果跑出来。

 

在 PostgreSQL9.4以后,聚合函数新增 FILTER 属性,我们可以使用这种新特性来代替 case when 写法,使得SQL语句看起来更加简洁、优雅。

等价改写方式2:

select count(*) filter ( where procinst.state_ in ('active') and wf.bus_num1 <= days ) ZB,
       count(*) filter ( where procinst.state_ in ('ended') and wf.bus_num1 <= days )  BJ,
       count(*) filter ( where procinst.state_ in ('active') and wf.bus_num1 > days )  YQZB,
       count(*) filter ( where procinst.state_ in ('ended') and wf.bus_num1 > days)    YQBJ
from (select) v
         join AAAAAAAAA wf on wf.master_entity in ('ccccccccc', 'REGULATORY_PLAN_STAGE')
         left join ccccccccc xpc on xpc.id = wf.master_entity_key
         join EEEEEEEEEEE procinst on procinst.id_ = wf.proc_inst_id and procinst.state_ in ('active', 'ended')
         join lateral (select max(duedate) as expire_date
                       from DDDDDDDDD
                       where procinst_ = procinst.id_
                       group by procinst_) t_expire on true
         join LATERAL (select date_part('day', t_expire.expire_date - procinst.start_) days ) on true
where ((wf.master_entity = 'ccccccccc' and xpc.project_sort = 'XM_PROJECT_SPECIAL' )
    or (wf.master_entity = 'REGULATORY_PLAN_STAGE'));

 ZB | BJ  | YQBJ | YQZB 
----+-----+------+------
  0 | 154 |   12 |  128

执行计划2:

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=2048.60..2048.61 rows=1 width=32) (actual time=195.004..195.008 rows=1 loops=1)
   ->  Nested Loop  (cost=555.04..2040.02 rows=143 width=27) (actual time=43.858..194.401 rows=355 loops=1)
         ->  Nested Loop  (cost=554.62..1299.12 rows=13 width=45) (actual time=43.144..48.111 rows=355 loops=1)
               ->  Hash Left Join  (cost=554.34..1253.29 rows=13 width=31) (actual time=13.312..44.417 rows=366 loops=1)
                     Hash Cond: (wf.master_entity_key = xpc.id)
                     Filter: ((((wf.master_entity)::text = 'ccccccccc'::text) AND ((xpc.project_sort)::text = 'XM_PROJECT_SPECIAL'::text)) OR ((wf.master_entity)::text = 'REGULATORY_PLAN_STAGE'::text))
                     Rows Removed by Filter: 641
                     ->  Bitmap Heap Scan on AAAAAAAAA wf  (cost=487.62..1186.09 rows=183 width=54) (actual time=12.510..42.785 rows=1007 loops=1)
                           Recheck Cond: ((((master_entity)::text = 'ccccccccc'::text) AND ((master_entity)::text = ANY ('{ccccccccc,REGULATORY_PLAN_STAGE}'::text[]))) OR (((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text) AND ((master_entity)::text = ANY ('{ccccccccc,REGULATORY_PLAN_STAGE}'::text[]))))
                           Heap Blocks: exact=118
                           ->  BitmapOr  (cost=487.62..487.62 rows=190 width=0) (actual time=11.410..11.412 rows=0 loops=1)
                                 ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..358.21 rows=139 width=0) (actual time=8.181..8.181 rows=103217 loops=1)
                                       Index Cond: (((master_entity)::text = 'ccccccccc'::text) AND ((master_entity)::text = ANY ('{ccccccccc,REGULATORY_PLAN_STAGE}'::text[])))
                                 ->  Bitmap Index Scan on AAAAAAAAA_master_entity_idx  (cost=0.00..129.31 rows=50 width=0) (actual time=3.228..3.228 rows=36061 loops=1)
                                       Index Cond: (((master_entity)::text = 'REGULATORY_PLAN_STAGE'::text) AND ((master_entity)::text = ANY ('{ccccccccc,REGULATORY_PLAN_STAGE}'::text[])))
                     ->  Hash  (cost=57.43..57.43 rows=743 width=23) (actual time=0.792..0.792 rows=743 loops=1)
                           Buckets: 1024  Batches: 1  Memory Usage: 49kB
                           ->  Seq Scan on ccccccccc xpc  (cost=0.00..57.43 rows=743 width=23) (actual time=0.010..0.578 rows=743 loops=1)
               ->  Index Scan using idx_getsummy_p on EEEEEEEEEEE procinst  (cost=0.28..3.52 rows=1 width=40) (actual time=0.009..0.009 rows=1 loops=366)
                     Index Cond: ((id_)::text = (wf.proc_inst_id)::text)
                     Filter: ((state_)::text = ANY ('{active,ended}'::text[]))
                     Rows Removed by Filter: 0
         ->  GroupAggregate  (cost=0.41..56.77 rows=11 width=34) (actual time=0.411..0.411 rows=1 loops=355)
               Group Key: DDDDDDDDD.procinst_
               ->  Index Scan using DDDDDDDDD_procinst__idx on DDDDDDDDD  (cost=0.41..56.61 rows=11 width=34) (actual time=0.392..0.405 rows=9 loops=355)
                     Index Cond: ((procinst_)::text = (procinst.id_)::text)
 Planning Time: 0.927 ms
 Execution Time: 195.131 ms
(28 rows)

使用聚合 filter 改写后可以看到只需要 195ms 就能把结果跑出来,比 case when 写法效率提高 50% ,SQL更加美观,真正实现了代码越少,效率越高的性能。

总结:写SQL尽量少用标量子查询。

 

posted @ 2023-01-30 17:35  小至尖尖  阅读(164)  评论(0编辑  收藏  举报