SQL优化-子查询结果集过多
这个优化案例是一个实际的业务场景,朋友公司从商业数据库迁移到PG中,测试中发现性能存在问题,同等数据量在商业数据库中不到秒级就出结果,但是在PG中缺需要几分钟甚至更久。
经过优化对SQL的改写效果还是不错,这里与大家分享下。
现象
最大的一张主表T98_SYT_ACCT_STAT_D_1有5.8亿,其余的都是百万级
原始SQL语句如下:
selectorg.Internal_Org_Id as Stat_Org_Id,(case when org.Internal_Org_Id = '999999888'then '合计'else org.Org_Nameend ) as Stat_Org_Name,(case when org.Internal_Org_Id = '999999888'then 1else 2end) as ORDERID,sum(data.jon_acct_num) as jon_acct_num,sum(data.jon_cross_num) as jon_cross_num,sum(data.jon_pay_num) as jon_pay_num,sum(data.total_jon_num) as total_jon_num,sum(data.des_acct_num) as des_acct_num,sum(data.des_cross_num) as des_cross_num,sum(data.des_pay_num) as des_pay_num,sum(data.total_des_num) as total_des_num,sum(data.accjon_acct_num) as accjon_acct_num,sum(data.accjon_cross_num) as accjon_cross_num,sum(data.accjon_pay_num) as accjon_pay_num,sum(data.total_accjon_num) as total_accjon_num,sum(data.accjon_acct_amt) as accjon_acct_amt,sum(data.accjon_cross_amt) as accjon_cross_amt,sum(data.accjon_acct1_amt) as accjon_acct1_amt,sum(data.accjon_acct0_amt) as accjon_acct0_amt,sum(data.accjon_pay_amt) as accjon_pay_amt,sum(data.total_accjon_amt) as total_accjon_amtfrom cimfbview.t98_int_org_app_rela_h orgleft join(selectsyt.Stat_Org_Id as Stat_Org_Id,sum(syt.jon_acct_num) as jon_acct_num,sum(syt.jon_cross_num) as jon_cross_num,sum(syt.jon_pay_num) as jon_pay_num,sum(syt.total_jon_num) as total_jon_num,sum(syt.des_acct_num) as des_acct_num,sum(syt.des_cross_num) as des_cross_num,sum(syt.des_pay_num) as des_pay_num,sum(syt.total_des_num) as total_des_num,sum(syt.accjon_acct_num) as accjon_acct_num,sum(syt.accjon_cross_num) as accjon_cross_num,sum(syt.accjon_pay_num) as accjon_pay_num,sum(syt.total_accjon_num) as total_accjon_num,sum(syt.accjon_acct_amt) as accjon_acct_amt,sum(syt.accjon_cross_amt) as accjon_cross_amt,sum(syt.accjon_acct1_amt) as accjon_acct1_amt,sum(syt.accjon_acct0_amt) as accjon_acct0_amt,sum(syt.accjon_pay_amt) as accjon_pay_amt,sum(syt.total_accjon_amt) as total_accjon_amtfrom T98_SYT_ACCT_STAT_D_1 sytwhere syt.Stat_Period_Cd = '1'and syt.Summ_Date = to_date('20161001','yyyymmdd')and syt.Stat_Org_Attr_Cd = '9'group by 1) dataon org.Internal_Org_Id=data.Stat_Org_Idwhere (org.Internal_Org_Id = '999999888'OR ORG.Parent_Int_Org_Id = '999999888'or '999999888' =(casewhen '1' = '1' and '2' in ('2','3') then nation_org_idwhen '1' = '2' and '2' in ('3','4','5') then prov_org_idwhen '1' = '3' and '2' in ('4','5') then city_org_idwhen '1' = '4' and '2' = '5' then county_org_idelse Internal_Org_Idend)and org.Int_Org_level_cd in ('1','2'))and org.Int_Org_Stru_Type_Cd='1'and org.Int_Org_Type_Cd in ('01','07','10','05','99')and org.Start_Dt <= to_date('20161001','yyyymmdd')and org.End_Dt > to_date('20161001','yyyymmdd')group by 1,2,3;
查询比较慢我们首先查看执行计划:
GroupAggregate (cost=14409317.97..14409320.04 rows=18 width=622) (actual time=472510.542..472510.766 rows=37 loops=1)Group Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)-> Sort (cost=14409317.97..14409318.02 rows=18 width=622) (actual time=472510.519..472510.542 rows=37 loops=1)Sort Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)Sort Method: quicksort Memory: 34kB-> Merge Left Join (cost=14404111.77..14409317.60 rows=18 width=622) (actual time=472016.735..472510.437 rows=37 loops=1)Merge Cond: (a.internal_org_id = syt.stat_org_id)-> Sort (cost=68934.45..68934.49 rows=18 width=76) (actual time=452.103..452.133 rows=37 loops=1)Sort Key: a.internal_org_idSort Method: quicksort Memory: 29kB-> Gather (cost=1000.42..68934.07 rows=18 width=76) (actual time=131.356..451.966 rows=37 loops=1)Workers Planned: 2Workers Launched: 2-> Nested Loop Left Join (cost=0.42..67932.27 rows=8 width=76) (actual time=58.910..398.641 rows=12 loops=3)-> Parallel Seq Scan on t98_int_org_app_rela_h a (cost=0.00..67864.63 rows=8 width=51) (actualtime=58.773..398.006 rows=12 loops=3)Filter: ((int_org_stru_type_cd = '1'::bpchar) AND (start_dt <= to_date('20161001'::text, 'yyyymmdd'::text)) AND (end_dt > to_date('20161001'::text, 'yyyymmdd'::text)) AND (int_org_type_cd = ANY ('{01,07,10,05,99}'::bpchar[])) AND ((internal_org_id = '999999888'::bpchar) OR (parent_int_org_id = '999999888'::bpchar) OR (('999999888'::bpchar = CASE WHEN ('2'::text = ANY ('{2,3}'::text[])) THEN nation_org_id ELSE internal_org_id END) AND (int_org_level_cd = ANY ('{1,2}'::bpchar[])))))Rows Removed by Filter: 549182-> Index Scan using idx_3 on t04_sys_organization org3 (cost=0.42..8.44 rows=1 width=45) (actual time=0.041..0.042 rows=1 loops=37)Index Cond: ((a.new_org_id = internal_org_id) AND (sys_id = 'S20'::character(3)))Filter: (province_cd = 71)-> GroupAggregate (cost=14335177.32..14339939.28 rows=35483 width=586) (actual time=471564.595..472002.661 rows=56831 loops=1)Group Key: syt.stat_org_id-> Sort (cost=14335177.32..14335317.84 rows=56208 width=100) (actual time=471564.558..471606.793 rows=56832loops=1)Sort Key: syt.stat_org_idSort Method: quicksort Memory: 9529kB-> Gather (cost=1000.00..14330742.93 rows=56208 width=100) (actual time=70985.797..471057.045 rows=56833 loops=1)Workers Planned: 2Workers Launched: 2-> Parallel Seq Scan on t98_syt_acct_stat_d_1 syt (cost=0.00..14324122.13 rows=23420 width=100)(actual time=71007.859..471086.192 rows=18944 loops=3)Filter: ((stat_period_cd = '1'::bpchar) AND (stat_org_attr_cd = '9'::bpchar) AND (summ_date= to_date('20161001'::text, 'yyyymmdd'::text)))Rows Removed by Filter: 186677461Planning time: 2.688 msExecution time: 472512.890 ms
通过执行计划看到t98_syt_acct_stat_d_1表并没有走到索引(其实表上是有索引),通过调整random_page_cost,seq_page_cost让优化器更偏向于走索引,得到的执行计划如下:
GroupAggregate (cost=9913849.82..9913851.89 rows=18 width=622) (actual time=166908.251..166908.659 rows=37 loops=1)Group Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)-> Sort (cost=9913849.82..9913849.86 rows=18 width=622) (actual time=166908.218..166908.259 rows=37 loops=1)Sort Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)Sort Method: quicksort Memory: 34kB-> Nested Loop Left Join (cost=1.43..9913849.44 rows=18 width=622) (actual time=138.763..166907.954 rows=37 loops=1)-> Merge Left Join (cost=1.00..9913805.16 rows=18 width=627) (actual time=138.717..166905.751 rows=37 loops=1)Merge Cond: (a.internal_org_id = syt.stat_org_id)-> Index Scan using idx_2 on t98_int_org_app_rela_h a (cost=0.43..74380.19 rows=18 width=51) (actual time=14.101..2392.532 rows=37 loops=1)Index Cond: (int_org_stru_type_cd = '1'::bpchar)Filter: ((start_dt <= to_date('20161001'::text, 'yyyymmdd'::text)) AND (end_dt > to_date('20161001'::text, 'yyyymmdd'::text)) AND (int_org_type_cd = ANY ('{01,07,10,05,99}'::bpchar[])) AND ((internal_org_id = '999999888'::bpchar) OR(parent_int_org_id = '999999888'::bpchar) OR (('999999888'::bpchar = CASE WHEN ('2'::text = ANY ('{2,3}'::text[])) THEN nation_org_id ELSE internal_org_id END) AND (int_org_level_cd = ANY ('{1,2}'::bpchar[])))))Rows Removed by Filter: 415239-> GroupAggregate (cost=0.58..9838981.24 rows=35483 width=586) (actual time=69.743..164300.902 rows=56831 loops=1)Group Key: syt.stat_org_id-> Index Scan using idx_1 on t98_syt_acct_stat_d_1 syt (cost=0.58..9834359.79 rows=56208 width=100) (actual time=45.638..163209.973 rows=56832 loops=1)Index Cond: ((summ_date = to_date('20161001'::text, 'yyyymmdd'::text)) AND (stat_period_cd = '1'::bpchar) AND (stat_org_attr_cd = '9'::bpchar))-> Index Scan using idx_3 on t04_sys_organization org3 (cost=0.42..2.45 rows=1 width=45) (actual time=0.041..0.043 rows=1 loops=37)Index Cond: ((a.new_org_id = internal_org_id) AND (sys_id = 'S20'::character(3)))Filter: (province_cd = 71)Planning time: 2.604 msExecution time: 166909.087 ms
可以看到通过走索引后时间减少了一半多,仔细观察执行计划在此处COST值消耗较大并且后续还有一个Merge Left Join,子查询数据返回太多导致后面做Merge时效率也很低。t98_syt_acct_stat_d_1这个表数据量最大5.8亿
Index Scan using idx_1 on t98_syt_acct_stat_d_1 syt (cost=0.58..9834359.79 rows=56208 width=100) (actual time=45.638..163209.973 rows=56832 loops=1)Index Cond: ((summ_date = to_date('20161001'::text, 'yyyymmdd'::text)) AND (stat_period_cd = '1'::bpchar) AND (stat_org_attr_cd = '9'::bpchar))
解决方案
我们需要较少子查询返回的结果集,观察SQL语句中的这部分
on org.Internal_Org_Id=data.Stat_Org_Idwhere (org.Internal_Org_Id = '999999888'OR ORG.Parent_Int_Org_Id = '999999888'or '999999888' =(casewhen '1' = '1' and '2' in ('2','3') then nation_org_idwhen '1' = '2' and '2' in ('3','4','5') then prov_org_idwhen '1' = '3' and '2' in ('4','5') then city_org_idwhen '1' = '4' and '2' = '5' then county_org_idelse Internal_Org_Idend)and org.Int_Org_level_cd in ('1','2'))and org.Int_Org_Stru_Type_Cd='1'and org.Int_Org_Type_Cd in ('01','07','10','05','99')and org.Start_Dt <= to_date('20161001','yyyymmdd')and org.End_Dt > to_date('20161001','yyyymmdd')
org.Internal_Org_Id=data.Stat_Org_Id , 后面的where条件是org表的过滤条件,我们将此过滤条件放到子查询中减少子查询返回的结果集,这样可以提高效率
改写后的SQL及执行计划:
selectorg.Internal_Org_Id as Stat_Org_Id --机构编号,(case when org.Internal_Org_Id = '999999888'then '合计'else org.Org_Nameend ) as Stat_Org_Name --机构代码,(case when org.Internal_Org_Id = '999999888'then 1else 2end) as ORDERID,sum(data.jon_acct_num) as jon_acct_num,sum(data.jon_cross_num) as jon_cross_num,sum(data.jon_pay_num) as jon_pay_num,sum(data.total_jon_num) as total_jon_num,sum(data.des_acct_num) as des_acct_num,sum(data.des_cross_num) as des_cross_num,sum(data.des_pay_num) as des_pay_num,sum(data.total_des_num) as total_des_num,sum(data.accjon_acct_num) as accjon_acct_num,sum(data.accjon_cross_num) as accjon_cross_num,sum(data.accjon_pay_num) as accjon_pay_num,sum(data.total_accjon_num) as total_accjon_num,sum(data.accjon_acct_amt) as accjon_acct_amt,sum(data.accjon_cross_amt) as accjon_cross_amt,sum(data.accjon_acct1_amt) as accjon_acct1_amt,sum(data.accjon_acct0_amt) as accjon_acct0_amt,sum(data.accjon_pay_amt) as accjon_pay_amt,sum(data.total_accjon_amt) as total_accjon_amtfrom cimfbview.t98_int_org_app_rela_h orgleft join(selectsyt.Stat_Org_Id as Stat_Org_Id,sum(syt.jon_acct_num) as jon_acct_num,sum(syt.jon_cross_num) as jon_cross_num,sum(syt.jon_pay_num) as jon_pay_num,sum(syt.total_jon_num) as total_jon_num,sum(syt.des_acct_num) as des_acct_num,sum(syt.des_cross_num) as des_cross_num,sum(syt.des_pay_num) as des_pay_num,sum(syt.total_des_num) as total_des_num,sum(syt.accjon_acct_num) as accjon_acct_num,sum(syt.accjon_cross_num) as accjon_cross_num,sum(syt.accjon_pay_num) as accjon_pay_num,sum(syt.total_accjon_num) as total_accjon_num,sum(syt.accjon_acct_amt) as accjon_acct_amt,sum(syt.accjon_cross_amt) as accjon_cross_amt,sum(syt.accjon_acct1_amt) as accjon_acct1_amt,sum(syt.accjon_acct0_amt) as accjon_acct0_amt,sum(syt.accjon_pay_amt) as accjon_pay_amt,sum(syt.total_accjon_amt) as total_accjon_amtfrom T98_SYT_ACCT_STAT_D_1 sytwhere syt.Stat_Period_Cd = '1'and syt.Summ_Date = to_date('20161001','yyyymmdd')and syt.Stat_Org_Attr_Cd = '9'and syt.Stat_Org_Id in (select distinct(Internal_Org_Id) from t98_int_org_app_rela_h org where org.Internal_Org_Id = '999999888'OR ORG.Parent_Int_Org_Id = '999999888'or '999999888' =(casewhen '1' = '1' and '2' in ('2','3') then nation_org_idwhen '1' = '2' and '2' in ('3','4','5') then prov_org_idwhen '1' = '3' and '2' in ('4','5') then city_org_idwhen '1' = '4' and '2' = '5' then county_org_idelse Internal_Org_Idend)and org.Int_Org_level_cd in ('1','2')and org.Int_Org_Stru_Type_Cd='1'and org.Int_Org_Type_Cd in ('01','07','10','05','99')and org.Start_Dt <= to_date('20161001','yyyymmdd')and org.End_Dt > to_date('20161001','yyyymmdd'))group by 1) dataon org.Internal_Org_Id=data.Stat_Org_Idwhere (org.Internal_Org_Id = '999999888'OR ORG.Parent_Int_Org_Id = '999999888'or '999999888' =(casewhen '1' = '1' and '2' in ('2','3') then nation_org_idwhen '1' = '2' and '2' in ('3','4','5') then prov_org_idwhen '1' = '3' and '2' in ('4','5') then city_org_idwhen '1' = '4' and '2' = '5' then county_org_idelse Internal_Org_Idend)and org.Int_Org_level_cd in ('1','2'))and org.Int_Org_Stru_Type_Cd='1'and org.Int_Org_Type_Cd in ('01','07','10','05','99')and org.Start_Dt <= to_date('20161001','yyyymmdd')and org.End_Dt > to_date('20161001','yyyymmdd')group by 1,2,3;GroupAggregate (cost=140463.35..140465.42 rows=18 width=622) (actual time=548.831..549.113 rows=37 loops=1)Group Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)-> Sort (cost=140463.35..140463.40 rows=18 width=622) (actual time=548.789..548.817 rows=37 loops=1)Sort Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)Sort Method: quicksort Memory: 34kB-> Nested Loop Left Join (cost=69906.79..140462.98 rows=18 width=622) (actual time=520.434..548.664 rows=37 loops=1)Join Filter: (a.internal_org_id = data.stat_org_id)Rows Removed by Join Filter: 669-> Gather (cost=1000.42..68934.07 rows=18 width=76) (actual time=63.704..89.506 rows=37 loops=1)Workers Planned: 2Workers Launched: 2-> Nested Loop Left Join (cost=0.42..67932.27 rows=8 width=76) (actual time=61.970..389.321 rows=12 loops=3)-> Parallel Seq Scan on t98_int_org_app_rela_h a (cost=0.00..67864.63 rows=8 width=51) (actual time=61.885..388.864 rows=12 loops=3)Filter: ((int_org_stru_type_cd = '1'::bpchar) AND (start_dt <= to_date('20161001'::text, 'yyyymmdd'::text)) AND (end_dt > to_date('20161001'::text, 'yyyymmdd'::text)) AND (int_org_type_cd = ANY ('{01,07,10,05,99}'::bpchar[])) AND ((internal_org_id = '999999888'::bpchar) OR (parent_int_org_id = '999999888'::bpchar) OR (('999999888'::bpchar = CASE WHEN ('2'::text = ANY ('{2,3}'::text[])) THEN nation_org_id ELSE internal_org_id END) AND (int_org_level_cd = ANY ('{1,2}'::bpchar[])))))Rows Removed by Filter: 549182-> Index Scan using idx_3 on t04_sys_organization org3 (cost=0.42..8.44 rows=1 width=45) (actual time=0.027..0.029 rows=1 loops=37)Index Cond: ((a.new_org_id = internal_org_id) AND (sys_id = 'S20'::character(3)))Filter: (province_cd = 71)-> Materialize (cost=68906.37..71450.71 rows=292 width=586) (actual time=12.309..12.389 rows=19 loops=37)-> Subquery Scan on data (cost=68906.37..71449.25 rows=292 width=586) (actual time=455.410..457.807 rows=40loops=1)-> GroupAggregate (cost=68906.37..71446.33 rows=292 width=586) (actual time=455.407..457.739 rows=40loops=1)Group Key: syt.stat_org_id-> Nested Loop (cost=68906.37..71416.40 rows=292 width=100) (actual time=455.322..457.390 rows=41 loops=1)-> Unique (cost=68905.79..68907.25 rows=291 width=10) (actual time=455.259..456.424 rows=44 loops=1)-> Sort (cost=68905.79..68906.52 rows=292 width=10) (actual time=455.255..455.810 rows=710 loops=1)Sort Key: org.internal_org_idSort Method: quicksort Memory: 58kB-> Gather (cost=1000.00..68893.83 rows=292 width=10) (actual time=0.683..453.986 rows=725 loops=1)Workers Planned: 2Workers Launched: 2-> Parallel Seq Scan on t98_int_org_app_rela_h org (cost=0.00..67864.63rows=122 width=10) (actual time=2.719..448.507 rows=242 loops=3)Filter: ((internal_org_id = '999999888'::bpchar) OR (parent_int_org_id = '999999888'::bpchar) OR (('999999888'::bpchar = CASE WHEN ('2'::text = ANY ('{2,3}'::text[])) THEN nation_org_id ELSE internal_org_id END) AND (int_org_level_cd = ANY ('{1,2}'::bpchar[])) AND (int_org_stru_type_cd = '1'::bpchar) AND (int_org_type_cd = ANY ('{01,07,10,05,99}'::bpchar[])) AND (start_dt <= to_date('20161001'::text, 'yyyymmdd'::text)) AND (end_dt > to_date('20161001'::text, 'yyyymmdd'::text))))Rows Removed by Filter: 548953-> Index Scan using idx_1 on t98_syt_acct_stat_d_1 syt (cost=0.58..8.60 rows=1 width=100)(actual time=0.016..0.017 rows=1 loops=44)Index Cond: ((stat_org_id = org.internal_org_id) AND (summ_date = to_date('20161001'::text, 'yyyymmdd'::text)) AND (stat_period_cd = '1'::bpchar) AND (stat_org_attr_cd = '9'::bpchar))Planning time: 2.997 msExecution time: 565.724 ms
执行时间缩小到不到1秒,通过执行计划看到SQL执行顺序发生了变化,t98_syt_acct_stat_d_1不是最先被执行的,而是先过滤完internal_org_id,再根据internal_org_id与t98_syt_acct_stat_d_1上的stat_org_id做 Nested Loop
还有一种方式可以将子查询提出来改成连接,这种方式SQL语句看起来比较清爽, 效率也不错
selectorg.Internal_Org_Id as Stat_Org_Id --机构编号,(case when org.Internal_Org_Id = '999999888'then '合计'else org.Org_Nameend ) as Stat_Org_Name --机构代码,(case when org.Internal_Org_Id = '999999888'then 1else 2end) as ORDERID,sum(data.jon_acct_num ) as jon_acct_num,sum(data.jon_cross_num ) as jon_cross_num,sum(data.jon_pay_num ) as jon_pay_num,sum(data.total_jon_num ) as total_jon_num,sum(data.des_acct_num ) as des_acct_num,sum(data.des_cross_num ) as des_cross_num,sum(data.des_pay_num ) as des_pay_num,sum(data.total_des_num ) as total_des_num,sum(data.accjon_acct_num ) as accjon_acct_num,sum(data.accjon_cross_num ) as accjon_cross_num,sum(data.accjon_pay_num ) as accjon_pay_num,sum(data.total_accjon_num ) as total_accjon_num,sum(data.accjon_acct_amt ) as accjon_acct_amt,sum(data.accjon_cross_amt ) as accjon_cross_amt,sum(data.accjon_acct1_amt ) as accjon_acct1_amt,sum(data.accjon_acct0_amt ) as accjon_acct0_amt,sum(data.accjon_pay_amt ) as accjon_pay_amt,sum(data.total_accjon_amt ) as total_accjon_amtfrom cimfbview.t98_int_org_app_rela_h orgleft join T98_SYT_ACCT_STAT_D_1 dataon org.Internal_Org_Id=data.Stat_Org_Idand data.Stat_Period_Cd = '1'and data.Summ_Date = to_date('20161001','yyyymmdd')and data.Stat_Org_Attr_Cd = '9'where (org.Internal_Org_Id = '999999888'OR ORG.Parent_Int_Org_Id = '999999888'or '999999888' =(casewhen '1' = '1' and '2' in ('2','3') then nation_org_idwhen '1' = '2' and '2' in ('3','4','5') then prov_org_idwhen '1' = '3' and '2' in ('4','5') then city_org_idwhen '1' = '4' and '2' = '5' then county_org_idelse Internal_Org_Idend)and org.Int_Org_level_cd in ('1','2'))and org.Int_Org_Stru_Type_Cd='1'and org.Int_Org_Type_Cd in ('01','07','10','05','99')and org.Start_Dt <= to_date('20161001','yyyymmdd')and org.End_Dt > to_date('20161001','yyyymmdd')group by 1,2,3order by 1,2,3;GroupAggregate (cost=69003.44..69005.51 rows=18 width=622) (actual time=401.488..401.925 rows=37 loops=1)Group Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)-> Sort (cost=69003.44..69003.48 rows=18 width=136) (actual time=401.431..401.487 rows=37 loops=1)Sort Key: a.internal_org_id, (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN '合计'::character varying ELSE COALESCE(org3.org_name, a.org_name) END), (CASE WHEN (a.internal_org_id = '999999888'::bpchar) THEN 1 ELSE 2 END)Sort Method: quicksort Memory: 34kB-> Gather (cost=1001.00..69003.06 rows=18 width=136) (actual time=61.302..401.261 rows=37 loops=1)Workers Planned: 2Workers Launched: 2-> Nested Loop Left Join (cost=1.00..68001.21 rows=8 width=136) (actual time=56.932..395.159 rows=12 loops=3)-> Nested Loop Left Join (cost=0.42..67932.27 rows=8 width=76) (actual time=56.841..394.613 rows=12 loops=3)-> Parallel Seq Scan on t98_int_org_app_rela_h a (cost=0.00..67864.63 rows=8 width=51) (actual time=56.745..394.173 rows=12 loops=3)Filter: ((int_org_stru_type_cd = '1'::bpchar) AND (start_dt <= to_date('20161001'::text, 'yyyymmdd'::text)) AND (end_dt > to_date('20161001'::text, 'yyyymmdd'::text)) AND (int_org_type_cd = ANY ('{01,07,10,05,99}'::bpchar[])) AND ((internal_org_id = '999999888'::bpchar) OR (parent_int_org_id = '999999888'::bpchar) OR (('999999888'::bpchar = CASE WHEN ('2'::text = ANY ('{2,3}'::text[])) THEN nation_org_id ELSE internal_org_id END) AND (int_org_level_cd = ANY ('{1,2}'::bpchar[])))))Rows Removed by Filter: 549182-> Index Scan using idx_3 on t04_sys_organization org3 (cost=0.42..8.44 rows=1 width=45) (actual time=0.026..0.027 rows=1 loops=37)Index Cond: ((a.new_org_id = internal_org_id) AND (sys_id = 'S20'::character(3)))Filter: (province_cd = 71)-> Index Scan using idx_1 on t98_syt_acct_stat_d_1 data (cost=0.58..8.60 rows=1 width=100) (actual time=0.034..0.036 rows=1 loops=37)Index Cond: ((a.internal_org_id = stat_org_id) AND (summ_date = to_date('20161001'::text, 'yyyymmdd'::text)) AND (stat_period_cd = '1'::bpchar) AND (stat_org_attr_cd = '9'::bpchar))Planning time: 4.092 msExecution time: 412.283 ms
总结
优化就是减少对数据扫描次数,子查询或连接查询时应尽量将结果集在底层减少数据结果
观察执行计划要看按执行顺序查看,这样才会发现哪一步执行计划出现了问题、返回的数据量最大、COST值消耗最大
数据库都是相通的这里数据库是PG但MySQL优化思路也一样。