优化案例3:高频多union表关联穿插拼接完成计数

news2024/10/7 20:29:47

优化案例3:高频多union表关联穿插拼接完成计数

  • 1. 引入
  • 2. 解决过程
    • 2.1 瓶颈定位思想
    • 2.2 定位解决过程
      • 2.2.1 子部分代码1
      • 2.2.2 子部分代码2
    • 2.3 优化结果
  • 3. 优化心得

DM技术交流QQ群:940124259

1. 引入

已经很久没有发布文章,快沉底!赶紧拿近期优化的案例分享一下,本次分享的主要知识是快速定位SQL瓶颈点以及SQL分析函数的等价改写。
本例SQL代码比较长(几百行),特征是大量的多表外关联,穿插几处union all拼接结果集(集合操作),其中一些不重要的部分会一笔带过,着重讲解关键点。


2. 解决过程

2.1 瓶颈定位思想

遇到特别长的SQL,想快速找出瓶颈位置,就要充分掌握拆分思想,即一段一段拆分出符合语法语义的子SQL尝试执行,找出性能最差的子SQL,再花精力攻克它。

比如本案例的特征union all多处拼接,可以以union all作为划分界限,逐步跟踪子语句性能。

-- 经脱敏处理的完整SQL代码
select count(1) 
  from ( SELECT XMXX.IS_LOW_RISK, 
                 XMXX.ID, 
                 XMXX.REPORT_TYPE, 
                 XMXX.TYPE, 
                 XMXX.TYPE AS STAGE, 
                 XMXX.STATUS, 
                 XMXX.CODE, 
                 XMXX.NAME, 
                 XMXX.OLD_ID, 
                 XMXX.CUR_DEPARTMENT_GUID, 
                 XMXX.CUR_OFFICE_GUID, 
                 XMXX.CUR_USER_ID, 
                 XMXX.ATTEND_STATUS, 
                 XMXX.APPLY_TIME, 
                 XMXX.APPLY_TIME as update_time, 
                 PRO_COUNTY.COUNTY, 
                 PRO_JSXZ.JSXZ, 
                 XMXX.SYS_FLAG, 
                 XMXX.VERSION, 
                 XMXX.TOTAL_INVEST, 
                 DE.department_fullname AS approve_dept_name, 
                 DE.parent_guid, 
                 DE.store_level, 
                 OWN.TYPE OWN_TYPE, 
                 XMXX.LEGAL, 
                 OWN.COMPANY_NAME COMPANY_NAME, 
                 '0' as xmflag , 
                 XMXX.is_ppp_item 
            FROM SHB_CQCQ XMXX 
       LEFT JOIN SHB_USER_INFO OWN 
              ON OWN.USER_ID = XMXX.CREATE_USER_ID 
       LEFT JOIN( SELECT ITEM_FULL_VALUE COUNTY, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1008') PRO_COUNTY 
              ON PRO_COUNTY.ITEM_KEY = XMXX.COUNTY 
       LEFT JOIN( SELECT ITEM_FULL_VALUE JSXZ, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1009') PRO_JSXZ 
              ON PRO_JSXZ.ITEM_KEY = XMXX.JSXZ 
       LEFT JOIN DEPARTMENT DE 
              ON XMXX.duty_department_id = DE.DEPARTMENT_GUID 
       LEFT JOIN (SELECT MAX(CUR_DEAL_TIME) AS CUR_DEAL_TIME, 
                          RELATE_BILL_ID 
                     FROM SHB_TO_DEAL_LOG 
                    WHERE TYPE = 'SHB-OPT-08' 
                 GROUP BY RELATE_BILL_ID) TD 
              ON TD.RELATE_BILL_ID = XMXX.ID 
           WHERE XMXX.IS_DEL = '0' 
             AND (XMXX.REPORT_TYPE NOT IN('3', 
                                          '2') 
                        OR (XMXX.REPORT_TYPE IN('3', 
                                                '2') 
                                 and (XMXX.ATTEND_STATUS <>50 
                                            or XMXX.ATTEND_STATUS IS NULL))) 
             AND IS_SHOW = 0 
             AND XMXX.COUNTY in ('CQ50011001', 
                                 'CQ50011002') 
             AND XMXX.status not in ('10') 
             AND ( XMXX.NAME LIKE '%重庆重庆%' 
                        OR XMXX.LEGAL LIKE '%重庆重庆%' 
                        OR XMXX.CODE LIKE '%重庆重庆%') 
       Union All 
          SELECT '0' as IS_LOW_RISK, 
                 XMXX.ID, 
                 XMXX.REPORT_TYPE, 
                 XMXX.TYPE, 
                 XMXX.TYPE AS STAGE, 
                 XMXX.STATUS, 
                 XMXX.CODE, 
                 XMXX.NAME, 
                 XMXX.OLD_ID, 
                 XMXX.CUR_DEPARTMENT_GUID, 
                 XMXX.CUR_OFFICE_GUID, 
                 XMXX.CUR_USER_ID, 
                 XMXX.ATTEND_STATUS, 
                 XMXX.APPLY_TIME, 
                 XMXX.APPLY_TIME as update_time, 
                 PRO_COUNTY.COUNTY, 
                 PRO_JSXZ.JSXZ, 
                 XMXX.SYS_FLAG, 
                 XMXX.VERSION, 
                 XMXX.TOTAL_INVEST, 
                 DE.department_fullname AS approve_dept_name, 
                 DE.parent_guid, 
                 DE.store_level, 
                 OWN.TYPE OWN_TYPE, 
                 XMXX.LEGAL, 
                 OWN.COMPANY_NAME COMPANY_NAME, 
                 '1' as xmflag, 
                 '0' as is_ppp_item 
            FROM SHB_CQCQ_TAGGING XMXX 
       LEFT JOIN SHB_USER_INFO OWN 
              ON OWN.USER_ID = XMXX.CREATE_USER_ID 
       LEFT JOIN( SELECT ITEM_FULL_VALUE COUNTY, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1008') PRO_COUNTY 
              ON PRO_COUNTY.ITEM_KEY = XMXX.COUNTY 
       LEFT JOIN( SELECT ITEM_FULL_VALUE JSXZ, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1009') PRO_JSXZ 
              ON PRO_JSXZ.ITEM_KEY = XMXX.JSXZ 
       LEFT JOIN DEPARTMENT DE 
              ON XMXX.duty_department_id = DE.DEPARTMENT_GUID 
       LEFT JOIN (SELECT MAX(CUR_DEAL_TIME) AS CUR_DEAL_TIME, 
                          RELATE_BILL_ID 
                     FROM SHB_TO_DEAL_LOG 
                    WHERE TYPE = 'SHB-OPT-08' 
                 GROUP BY RELATE_BILL_ID) TD 
              ON TD.RELATE_BILL_ID = XMXX.ID 
           WHERE XMXX.IS_DEL = '0' 
             AND (XMXX.REPORT_TYPE NOT IN('3', 
                                          '2') 
                        OR (XMXX.REPORT_TYPE IN('3', 
                                                '2') 
                                 and (XMXX.ATTEND_STATUS <>50 
                                            or XMXX.ATTEND_STATUS IS NULL))) 
             AND IS_SHOW = 0 
             AND XMXX.COUNTY in ('CQ50011001', 
                                 'CQ50011002') 
             AND XMXX.status not in ('10') 
             AND ( XMXX.NAME LIKE '%重庆重庆%' 
                        OR XMXX.LEGAL LIKE '%重庆重庆%' 
                        OR XMXX.CODE LIKE '%重庆重庆%') 
       Union All 
          SELECT XMXX.IS_LOW_RISK, 
                 px.ID, 
                 XMXX.REPORT_TYPE, 
                 XMXX.TYPE, 
                 XMXX.TYPE AS STAGE, 
                 XMXX.STATUS, 
                 XMXX.CODE, 
                 XMXX.NAME, 
                 px.SHB_CQCQ_id as OLD_ID, 
                 XMXX.CUR_DEPARTMENT_GUID, 
                 XMXX.CUR_OFFICE_GUID, 
                 XMXX.CUR_USER_ID, 
                 XMXX.ATTEND_STATUS, 
                 XMXX.APPLY_TIME, 
                 XMXX.update_time, 
                 PRO_COUNTY.COUNTY, 
                 PRO_JSXZ.JSXZ, 
                 XMXX.SYS_FLAG, 
                 XMXX.VERSION, 
                 XMXX.TOTAL_INVEST, 
                 DE.department_fullname AS approve_dept_name, 
                 DE.parent_guid, 
                 DE.store_level, 
                 OWN.TYPE OWN_TYPE, 
                 XMXX.LEGAL, 
                 px.ppp_item_stage COMPANY_NAME, 
                 '2' as xmflag , 
                 XMXX.is_ppp_item 
            from SHB_CQCQ_ppp px 
            JOIN SHB_CQCQ XMXX 
              ON px.SHB_CQCQ_id=XMXX.id 
       LEFT JOIN SHB_USER_INFO OWN 
              ON OWN.USER_ID = XMXX.CREATE_USER_ID 
       LEFT JOIN( SELECT ITEM_FULL_VALUE COUNTY, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1008') PRO_COUNTY 
              ON PRO_COUNTY.ITEM_KEY = XMXX.COUNTY 
       LEFT JOIN( SELECT ITEM_FULL_VALUE JSXZ, 
                         ITEM_KEY 
                    FROM DICTIONARY_ITEMS 
                   WHERE GROUP_NO = '1009') PRO_JSXZ 
              ON PRO_JSXZ.ITEM_KEY = XMXX.JSXZ 
       LEFT JOIN DEPARTMENT DE 
              ON XMXX.duty_department_id = DE.DEPARTMENT_GUID 
           where 1=1 
             AND XMXX.COUNTY in ('CQ50011001', 
                                 'CQ50011002') 
             AND ( XMXX.NAME LIKE '%重庆重庆%' 
                        OR XMXX.LEGAL LIKE '%重庆重庆%' 
                        OR XMXX.CODE LIKE '%重庆重庆%') 
             AND px.pp_status in('33', 
                                 '50', 
                                 '40', 
                                 '12', 
                                 '41', 
                                 '71') 
       Union All 
       select E.* 
         from ( select distinct '0' AS IS_LOW_RISK, 
                        F.id, 
                        to_number('999') AS report_type, 
                        F.pro_type as type, 
                        F.apply_stage as stage, 
                        to_number(F.status) as status, 
                        F.gj_pro_code AS code, 
                        F.gj_pro_name AS name, 
                        '' as old_id, 
                        'CHONGQI-3' as CUR_DEPARTMENT_GUID, 
                        'CHONGQI-3' as CUR_OFFICE_GUID, 
                        '' as CUR_USER_ID, 
                        F.matters as attend_status, 
                        F.update_time as apply_time, 
                        F.update_time, 
                        pro_county.county, 
                        pro_jsxz.item_full_value AS jsxz, 
                        to_number('999') AS sys_flag, 
                        to_number('0') AS version, 
                        F.gj_investment_total as TOTAL_INVEST, 
                        '顶呱呱' as approve_dept_name, 
                        '' as parent_guid, 
                        to_number('000') as store_level, 
                        own.type AS own_type, 
                        F.gj_pro_org as legal, 
                        own.company_name, 
                        F.matters as xmflag, 
                        '' as is_ppp_item 
                   from ( select xmxx.total_invest as gj_investment_total, 
                                  pro.build_properties, 
                                  pro.gj_pro_org, 
                                  C.matters, 
                                  C.apply_stage, 
                                  C.pro_type, 
                                  C.id, 
                                  xmxx.code as gj_pro_code, 
                                  xmxx.name as gj_pro_name, 
                                  C.create_user_id, 
                                  pro.county, 
                                  C.apply_matters, 
                                  xmxx.status, 
                                  C.update_time 
                             from ( select 'inout_project' as matters, 
                                          A.apply_stage, 
                                          A.pro_type, 
                                          A.id, 
                                          A.project_id, 
                                          A.update_time, 
                                          A.create_user_id, 
                                          A.apply_matters 
                                     from service_inout_project A
                                    where A.is_del = '0' 
                                      and A.status in('01', 
                                                      '02', 
                                                      '11', 
                                                      '13', 
                                                      '21', 
                                                      '23', 
                                                      '12', 
                                                      '22', 
                                                      '15', 
                                                      '16', 
                                                      '17', 
                                                      '18', 
                                                      '25', 
                                                      '26', 
                                                      '27', 
                                                      '28', 
                                                      '14', 
                                                      '24')
                                  union all
                                  select 'free_project' as matters, 
                                         B.apply_stage, 
                                         B.pro_type, 
                                         B.id, 
                                         B.project_id, 
                                         B.update_time, 
                                         B.create_user_id, 
                                         B.apply_matters 
                                    from service_free_project B
                                   where B.is_del = '0' 
                                     and B.status in('01', 
                                                     '02', 
                                                     '11', 
                                                     '13', 
                                                     '21', 
                                                     '23', 
                                                     '12', 
                                                     '22', 
                                                     '15', 
                                                     '16', 
                                                     '17', 
                                                     '18', 
                                                     '25', 
                                                     '26', 
                                                     '27', 
                                                     '28', 
                                                     '14', 
                                                     '24')) C
                        left join cq_base_pro pro 
                               on pro.id = C.project_id 
                        left join SHB_CQCQ xmxx 
                               on xmxx.cq_base_pro_id = pro.id 
                              and xmxx.is_del = '0'
                        union all
                           select info.total_money as gj_investment_total, 
                                  '' as build_properties, 
                                  '' as gj_pro_org, 
                                  E.matters, 
                                  E.apply_stage, 
                                  E.pro_type, 
                                  E.id, 
                                  info.project_code as gj_pro_code, 
                                  info.project_name as gj_pro_name, 
                                  E.create_user_id, 
                                  info.place_code as county, 
                                  E.apply_matters, 
                                  '' as status, 
                                  E.update_time 
                             from ( select 'free_project' as matters, 
                                          D.apply_stage, 
                                          D.pro_type, 
                                          D.id, 
                                          D.project_id, 
                                          D.update_time, 
                                          D.create_user_id, 
                                          D.apply_matters, 
                                          D.status 
                                     from service_free_project D 
                                    where D.is_del = '0' 
                                      and D.status in('01', 
                                                      '02', 
                                                      '11', 
                                                      '13', 
                                                      '21', 
                                                      '23', 
                                                      '12', 
                                                      '22', 
                                                      '15', 
                                                      '16', 
                                                      '17', 
                                                      '18', 
                                                      '25', 
                                                      '26', 
                                                      '27', 
                                                      '28', 
                                                      '14', 
                                                      '24')) E
                        left join region_apply_pro_info info 
                               on E.project_id = info.id ) F
              left join shb_user_info own 
                     on own.user_id = F.create_user_id
              left join (select item_full_value county, 
                                item_key 
                           from dictionary_items 
                          where group_no = '1008') pro_county
                     on pro_county.item_key = F.county
              left join ( select max(cur_deal_time) as cur_deal, 
                                 relate_bill_id
                            from shb_to_deal_log 
                           where cur_department_guid = 'CHONGQI-31' 
                        group by relate_bill_id ) td
                     on td.relate_bill_id = F.id 
              left join (select item_full_value, 
                                item_key 
                           from dictionary_items 
                          where group_no = '1009') pro_jsxz 
                     on pro_jsxz.item_key = F.build_properties 
                  where F.gj_pro_code is not null 
              union all 
                 select  distinct '' as is_low_risk , 
                        ch.id , 
                        xmxx.report_type , 
                        '8' as type , 
                        ch.apply_stage as stage , 
                        ch.status , 
                        ch.pro_code as code , 
                        ch.pro_name as name , 
                        xmxx.old_id , 
                        XMXX.CUR_DEPARTMENT_GUID , 
                        XMXX.CUR_OFFICE_GUID , 
                        XMXX.CUR_USER_ID , 
                        XMXX.ATTEND_STATUS , 
                        XMXX.APPLY_TIME, 
                        ch.update_time , 
                        pro_county.county , 
                        PRO_JSXZ.item_full_value as JSXZ , 
                        XMXX.SYS_FLAG , 
                        XMXX.VERSION , 
                        XMXX.TOTAL_INVEST, 
                        de.department_fullname as approve_dept_name, 
                        de.parent_guid , 
                        de.store_level , 
                        own.type as own_type , 
                        xmxx.legal , 
                        OWN.COMPANY_NAME COMPANY_NAME , 
                        'charter' as xmflag , 
                        xmxx.is_ppp_item 
                   from charter_project ch 
              left join cq_base_pro b 
                     on b.id = ch.cq_base_id 
              left join SHB_CQCQ xmxx 
                     on xmxx.cq_base_pro_id = ch.cq_base_id 
                    and xmxx.is_del = '0' 
              left join ( select item_full_value county, 
                                item_key 
                           from dictionary_items 
                          where group_no = '1008' ) pro_county 
                     on pro_county.item_key = xmxx.county 
              left join ( select item_full_value, 
                                item_key 
                           from dictionary_items 
                          where group_no = '1009' ) pro_jsxz 
                     on pro_jsxz.item_key = xmxx.jsxz 
              LEFT JOIN DEPARTMENT DE 
                     ON XMXX.duty_department_id = DE.DEPARTMENT_GUID 
              LEFT JOIN SHB_USER_INFO OWN 
                     ON OWN.USER_ID = XMXX.CREATE_USER_ID 
                  WHERE XMXX.COUNTY in ('CQ50011001', 
                                        'CQ50011002') 
                     or XMXX.COUNTY IS NULL 
              union all 
                 SELECT XMXX.IS_LOW_RISK ,
                        en.id ,
                        XMXX.REPORT_TYPE ,
                        XMXX.TYPE ,
                        en.apply_stage AS STAGE ,
                        en.STATUS ,
                        XMXX.CODE ,
                        XMXX.NAME ,
                        XMXX.OLD_ID ,
                        XMXX.CUR_DEPARTMENT_GUID ,
                        XMXX.CUR_OFFICE_GUID ,
                        XMXX.CUR_USER_ID ,
                        XMXX.ATTEND_STATUS ,
                        XMXX.APPLY_TIME ,
                        en.update_time ,
                        PRO_COUNTY.COUNTY ,
                        PRO_JSXZ.item_full_value as JSXZ ,
                        XMXX.SYS_FLAG ,
                        XMXX.VERSION ,
                        XMXX.TOTAL_INVEST ,
                        case when en.reply_level = '0' then '教室' else DE.department_fullname end AS approve_dept_name,
                        DE.parent_guid ,
                        DE.store_level ,
                        OWN.TYPE OWN_TYPE ,
                        XMXX.LEGAL ,
                        OWN.COMPANY_NAME COMPANY_NAME ,
                        'energy' as xmflag ,
                        XMXX.is_ppp_item
                   from energy_audit en
              left join ( select x.*
                              from SHB_CQCQ x
                        inner join ( select code, 
                                            max(create_time) utime 
                                       from SHB_CQCQ 
                                      where (status = '40' or type = '5') 
                                   group by code ) xx
                                on xx.code = x.code and x.create_time = xx.utime ) xmxx 
                     on xmxx.code = en.project_code
              left join ( select item_full_value county,
                                item_key
                           from dictionary_items
                          where group_no = '1008' ) pro_county
                     on pro_county.item_key = xmxx.county
              left join ( select item_full_value,
                                item_key
                           from dictionary_items
                          where group_no = '1009' ) pro_jsxz
                     on pro_jsxz.item_key = xmxx.jsxz
              LEFT JOIN DEPARTMENT DE
                     ON XMXX.duty_department_id = DE.DEPARTMENT_GUID
              LEFT JOIN SHB_USER_INFO OWN
                     ON OWN.USER_ID = XMXX.CREATE_USER_ID 
                  where 1=1 AND XMXX.COUNTY in ('CQ50011001', 
                                                'CQ50011002') ) E 
        where 1=1 AND ( E.name LIKE '%重庆重庆%' OR E.code LIKE '%重庆重庆%') ) TOTAL

2.2 定位解决过程

针对union all分支一个一个从上到下尝试执行,记录耗时,很快地追踪到有两处位置性能特别差。

2.2.1 子部分代码1

-- 脱敏SQL
select xmxx.total_invest as gj_investment_total, 
                                  pro.build_properties, 
                                  pro.gj_pro_org, 
                                  C.matters, 
                                  C.apply_stage, 
                                  C.pro_type, 
                                  C.id, 
                                  xmxx.code as gj_pro_code, 
                                  xmxx.name as gj_pro_name, 
                                  C.create_user_id, 
                                  pro.county, 
                                  C.apply_matters, 
                                  xmxx.status, 
                                  C.update_time 
                             from ( select 'inout_project' as matters, 
                                          A.apply_stage, 
                                          A.pro_type, 
                                          A.id, 
                                          A.project_id, 
                                          A.update_time, 
                                          A.create_user_id, 
                                          A.apply_matters 
                                     from service_inout_project A
                                    where A.is_del = '0' 
                                      and A.status in('01', 
                                                      '02', 
                                                      '11', 
                                                      '13', 
                                                      '21', 
                                                      '23', 
                                                      '12', 
                                                      '22', 
                                                      '15', 
                                                      '16', 
                                                      '17', 
                                                      '18', 
                                                      '25', 
                                                      '26', 
                                                      '27', 
                                                      '28', 
                                                      '14', 
                                                      '24')
                                  union all
                                  select 'free_project' as matters, 
                                         B.apply_stage, 
                                         B.pro_type, 
                                         B.id, 
                                         B.project_id, 
                                         B.update_time, 
                                         B.create_user_id, 
                                         B.apply_matters 
                                    from service_free_project B
                                   where B.is_del = '0' 
                                     and B.status in('01', 
                                                     '02', 
                                                     '11', 
                                                     '13', 
                                                     '21', 
                                                     '23', 
                                                     '12', 
                                                     '22', 
                                                     '15', 
                                                     '16', 
                                                     '17', 
                                                     '18', 
                                                     '25', 
                                                     '26', 
                                                     '27', 
                                                     '28', 
                                                     '14', 
                                                     '24')) C
                        left join cq_base_pro pro 
                               on pro.id = C.project_id 
                        left join SHB_CQCQ xmxx 
                               on xmxx.cq_base_pro_id = pro.id 
                              and xmxx.is_del = '0'                                                                      

代码1执行计划:一看执行计划步骤20就怀疑有问题,SHB_CQCQ AS
XMXX表大小567MB,表记录1123476,整体查询结果集返回2条。检查步骤4-18真实返回少,步骤19-20应该补建索引,根据步骤3计划得知关联字段XMXX.CQ_BASE_PRO_ID,则对它建一个单列索引。

-- 优化前执行计划
1   #NSET2: [79, 2, 648] 
2     #PRJT2: [79, 2, 648]; exp_num(14), is_atom(FALSE) 
3       #HASH LEFT JOIN2: [79, 2, 648]; key_num(1), partition_keys_num(0)  KEY(PRO.ID=XMXX.CQ_BASE_PRO_ID)
4         #INDEX JOIN LEFT JOIN2: [2, 2, 396] 
5           #PRJT2: [1, 2, 396]; exp_num(8), is_atom(FALSE) 
6             #UNION ALL: [1, 2, 396] 
7               #PRJT2: [0, 1, 396]; exp_num(8), is_atom(FALSE) 
8                 #HASH LEFT SEMI JOIN2: [0, 1, 396]; KEY_NUM(1);  KEY(A.STATUS=DMTEMPVIEW_17674615.colname) KEY_NULL_EQU(0)
9                   #SLCT2: [0, 1, 396]; A.IS_DEL = '0'
10                    #CSCN2: [0, 7, 396]; INDEX33559165(SERVICE_INOUT_PROJECT as A)
11                  #CONST VALUE LIST: [0, 18, 48]; row_num(18), col_num(1), 
12              #PRJT2: [0, 1, 396]; exp_num(8), is_atom(FALSE) 
13                #HASH LEFT SEMI JOIN2: [0, 1, 396]; KEY_NUM(1);  KEY(B.STATUS=DMTEMPVIEW_17674616.colname) KEY_NULL_EQU(0)
14                  #SLCT2: [0, 1, 396]; B.IS_DEL = '0'
15                    #CSCN2: [0, 1, 396]; INDEX33559166(SERVICE_FREE_PROJECT as B)
16                  #CONST VALUE LIST: [0, 18, 48]; row_num(18), col_num(1), 
17          #BLKUP2: [0, 1, 0]; INDEX33559875(PRO)
18            #SSEK2: [0, 1, 0]; scan_type(ASC), INDEX33559875(CQ_BASE_PRO as PRO), scan_range[C.PROJECT_ID,C.PROJECT_ID]
19        #SLCT2: [51, 256955, 252]; XMXX.IS_DEL = '0'
20          #CSCN2: [51, 311391, 252]; INDEX33559137(SHB_CQCQ as XMXX)   ************ 性能瓶颈点 ************

处理方法 :补建索引
create index idxfs_shb_CQCQ_cq_base_pro_id on cq.shb_CQCQ(cq_base_pro_id);

-- 优化后执行计划
1   #NSET2: [2, 9, 396] 
2     #PRJT2: [2, 9, 396]; exp_num(14), is_atom(FALSE) 
3       #INDEX JOIN LEFT JOIN2: [2, 9, 396] join condition(XMXX.IS_DEL = '0')
4         #INDEX JOIN LEFT JOIN2: [2, 2, 396] 
5           #PRJT2: [1, 2, 396]; exp_num(8), is_atom(FALSE) 
6             #UNION ALL: [1, 2, 396] 
7               #PRJT2: [0, 1, 396]; exp_num(8), is_atom(FALSE) 
8                 #HASH LEFT SEMI JOIN2: [0, 1, 396]; KEY_NUM(1);  KEY(A.STATUS=DMTEMPVIEW_17681581.colname) KEY_NULL_EQU(0)
9                   #SLCT2: [0, 1, 396]; A.IS_DEL = '0'
10                    #CSCN2: [0, 7, 396]; INDEX33559165(SERVICE_INOUT_PROJECT as A)
11                  #CONST VALUE LIST: [0, 18, 48]; row_num(18), col_num(1), 
12              #PRJT2: [0, 1, 396]; exp_num(8), is_atom(FALSE) 
13                #HASH LEFT SEMI JOIN2: [0, 1, 396]; KEY_NUM(1);  KEY(B.STATUS=DMTEMPVIEW_17681582.colname) KEY_NULL_EQU(0)
14                  #SLCT2: [0, 1, 396]; B.IS_DEL = '0'
15                    #CSCN2: [0, 1, 396]; INDEX33559166(SERVICE_FREE_PROJECT as B)
16                  #CONST VALUE LIST: [0, 18, 48]; row_num(18), col_num(1), 
17          #BLKUP2: [0, 1, 0]; INDEX33559875(PRO)
18            #SSEK2: [0, 1, 0]; scan_type(ASC), INDEX33559875(CQ_BASE_PRO as PRO), scan_range[C.PROJECT_ID,C.PROJECT_ID]
19        #BLKUP2: [0, 1, 0]; IDXFS_SHB_CQCQ_CQ_BASE_PRO_ID(XMXX)
20          #SSEK2: [0, 1, 0]; scan_type(ASC), IDXFS_SHB_CQCQ_CQ_BASE_PRO_ID(SHB_CQCQ as XMXX), scan_range[PRO.ID,PRO.ID]   ******* 优化效果点  *******

2.2.2 子部分代码2

-- 脱敏SQL
   SELECT XMXX.IS_LOW_RISK ,
                        en.id ,
                        XMXX.REPORT_TYPE ,
                        XMXX.TYPE ,
                        en.apply_stage AS STAGE ,
                        en.STATUS ,
                        XMXX.CODE ,
                        XMXX.NAME ,
                        XMXX.OLD_ID ,
                        XMXX.CUR_DEPARTMENT_GUID ,
                        XMXX.CUR_OFFICE_GUID ,
                        XMXX.CUR_USER_ID ,
                        XMXX.ATTEND_STATUS ,
                        XMXX.APPLY_TIME ,
                        en.update_time ,
                        PRO_COUNTY.COUNTY ,
                        PRO_JSXZ.item_full_value as JSXZ ,
                        XMXX.SYS_FLAG ,
                        XMXX.VERSION ,
                        XMXX.TOTAL_INVEST ,
                        case when en.reply_level = '0' then '教室' else DE.department_fullname end AS approve_dept_name,
                        DE.parent_guid ,
                        DE.store_level ,
                        OWN.TYPE OWN_TYPE ,
                        XMXX.LEGAL ,
                        OWN.COMPANY_NAME COMPANY_NAME ,
                        'energy' as xmflag ,
                        XMXX.is_ppp_item
                   from energy_audit en
              left join ( select x.*
                              from SHB_CQCQ x
                        inner join (select code, 
                                            max(create_time) utime 
                                       from SHB_CQCQ 
                                      where (status = '40' or type = '5') 
                                   group by code ) xx
                                on xx.code = x.code and x.create_time = xx.utime ) xmxx 
                     on xmxx.code = en.project_code
              left join ( select item_full_value county,
                                item_key
                           from dictionary_items
                          where group_no = '1008' ) pro_county
                     on pro_county.item_key = xmxx.county
              left join ( select item_full_value,
                                item_key
                           from dictionary_items
                          where group_no = '1009' ) pro_jsxz
                     on pro_jsxz.item_key = xmxx.jsxz
              LEFT JOIN DEPARTMENT DE
                     ON XMXX.duty_department_id = DE.DEPARTMENT_GUID
              LEFT JOIN SHB_USER_INFO OWN
                     ON OWN.USER_ID = XMXX.CREATE_USER_ID 
                  where 1=1 AND XMXX.COUNTY in ('CQ50011001', 
                                                'CQ50011002')   /*耗时985毫秒*/ 

子代码2的执行计划:看来SHB_CQCQ表属于业务核心表,哪哪都有它,反复的引用,体积有点大。
迅速怀疑(status = ‘40’ or type = ‘5’) 过滤条件很差,而优化器默认union分治再合并处理(步骤21-25),赶紧过滤查查select count(*) from shb_xmxx XMXX where (status = ‘40’ or type = ‘5’) ; – 235 931,返回的结果集比较大啦。
显然步骤21-25执行计划是错误的,应该考虑过滤条件合体,而不是拆分再合并(搞出步骤22的错误索引回表和步骤25的二次全表扫描),这个可以用hint optimizer_or_nbexp(2)解决。
再继续针对XMXX内联视图的查看,SHB_CQCQ as X又被执行了一次自关联,执行计划步骤26体现,显然这种不科学。他的初衷大致取每个项目最近的处理时间,完全没必要反复自关联这么搞,弄成分析函数作辅助列再过滤即可,减少一次SHB_CQCQ as X表的访问,性能自然而然地提高。

-- 未优化前执行计划
1   #NSET2: [1196, 7949, 7886] 
2     #PRJT2: [1196, 7949, 7886]; exp_num(28), is_atom(FALSE) 
3       #INDEX JOIN LEFT JOIN2: [1196, 7949, 7886] 
4         #INDEX JOIN LEFT JOIN2: [1187, 1295, 7886] 
5           #HASH RIGHT JOIN2: [1178, 1295, 7886]; key_num(1),  KEY(PRO_JSXZ.ITEM_KEY=XMXX.JSXZ)
6             #PRJT2: [1, 8, 144]; exp_num(2), is_atom(FALSE) 
7               #SLCT2: [1, 8, 144]; DICTIONARY_ITEMS.GROUP_NO = '1009'
8                 #CSCN2: [1, 9158, 144]; INDEX33559353(DICTIONARY_ITEMS)
9             #HASH RIGHT JOIN2: [1175, 1295, 7742]; key_num(1),  KEY(PRO_COUNTY.ITEM_KEY=XMXX.COUNTY)
10              #PRJT2: [1, 72, 144]; exp_num(2), is_atom(FALSE) 
11                #SLCT2: [1, 72, 144]; DICTIONARY_ITEMS.GROUP_NO = '1008'
12                  #CSCN2: [1, 9158, 144]; INDEX33559353(DICTIONARY_ITEMS)
13              #HASH2 INNER JOIN: [1171, 1295, 7598];  KEY_NUM(1); KEY(EN.PROJECT_CODE=XMXX.CODE) KEY_NULL_EQU(0)
14                #CSCN2: [0, 1328, 252]; INDEX33560566(ENERGY_AUDIT as EN)
15                #HASH RIGHT SEMI JOIN2: [1162, 7727, 7346]; n_keys(1)   KEY(DMTEMPVIEW_17697425.colname=XMXX.COUNTY) KEY_NULL_EQU(0)
16                  #CONST VALUE LIST: [0, 2, 48]; row_num(2), col_num(1), 
17                  #PRJT2: [1157, 154543, 7346]; exp_num(20), is_atom(FALSE) 
18                    #HASH2 INNER JOIN: [1157, 154543, 7346];  KEY_NUM(2); KEY(XX.CODE=X.CODE AND XX.UTIME=X.CREATE_TIME) KEY_NULL_EQU(0, 0)
19                      #PRJT2: [108, 227506, 146]; exp_num(2), is_atom(FALSE) 
20                        #HAGR2: [108, 227506, 146]; grp_num(1), sfun_num(1); slave_empty(0) keys(SHB_CQCQ.CODE) 
21                          #UNION FOR OR2: [86, 263623, 146]; key_num(1)     ************ 性能瓶颈点 ************
22                            #BLKUP2: [41, 36060, 146]; INDEX_NAME_TYPE(SHB_CQCQ)
23                              #SSEK2: [41, 36060, 146]; scan_type(ASC), INDEX_NAME_TYPE(SHB_CQCQ), scan_range['5','5']
24                            #SLCT2: [45, 227562, 146]; SHB_CQCQ.STATUS = var2
25                              #CSCN2: [45, 311391, 146]; INDEX33559137(SHB_CQCQ) 
26                      #CSCN2: [712, 311391, 7200]; INDEX33559137(SHB_CQCQ as X)   ************ 性能瓶颈点 ************
27          #BLKUP2: [8, 1, 0]; INDEX33559823(DE)
28            #SSEK2: [8, 1, 0]; scan_type(ASC), INDEX33559823(DEPARTMENT as DE), scan_range[XMXX.DUTY_DEPARTMENT_ID,XMXX.DUTY_DEPARTMENT_ID]
29        #BLKUP2: [9, 7, 0]; SHB_USER_INFO_USERID_INDEX(OWN)
30          #SSEK2: [9, 7, 0]; scan_type(ASC), SHB_USER_INFO_USERID_INDEX(SHB_USER_INFO as OWN), scan_range[XMXX.CREATE_USER_ID,XMXX.CREATE_USER_ID]

处理方法:分析函数等价改写和HINT处理OR不展开

-- 等价改写和HINT指定
     SELECT XMXX.IS_LOW_RISK ,
                        en.id ,
                        XMXX.REPORT_TYPE ,
                        XMXX.TYPE ,
                        en.apply_stage AS STAGE ,
                        en.STATUS ,
                        XMXX.CODE ,
                        XMXX.NAME ,
                        XMXX.OLD_ID ,
                        XMXX.CUR_DEPARTMENT_GUID ,
                        XMXX.CUR_OFFICE_GUID ,
                        XMXX.CUR_USER_ID ,
                        XMXX.ATTEND_STATUS ,
                        XMXX.APPLY_TIME ,
                        en.update_time ,
                        PRO_COUNTY.COUNTY ,
                        PRO_JSXZ.item_full_value as JSXZ ,
                        XMXX.SYS_FLAG ,
                        XMXX.VERSION ,
                        XMXX.TOTAL_INVEST ,
                        case when en.reply_level = '0' then '教室' else DE.department_fullname end AS approve_dept_name,
                        DE.parent_guid ,
                        DE.store_level ,
                        OWN.TYPE OWN_TYPE ,
                        XMXX.LEGAL ,
                        OWN.COMPANY_NAME COMPANY_NAME ,
                        'energy' as xmflag ,
                        XMXX.is_ppp_item
    from energy_audit en
              left join ( select /*+ optimizer_or_nbexp(2)*/xx.*
                            from (
                                select x.*, max(create_time) over(partition by code ) utime
                                from SHB_CQCQ x
                                where (status = '40' or type = '5') 
                            ) xx
                               where xx.utime = create_time
                        ) xmxx 
                     on xmxx.code = en.project_code
              left join ( select item_full_value county,
                                item_key
                           from dictionary_items
                          where group_no = '1008' ) pro_county
                     on pro_county.item_key = xmxx.county
              left join ( select item_full_value,
                                item_key
                           from dictionary_items
                          where group_no = '1009' ) pro_jsxz
                     on pro_jsxz.item_key = xmxx.jsxz
              LEFT JOIN DEPARTMENT DE
                     ON XMXX.duty_department_id = DE.DEPARTMENT_GUID
              LEFT JOIN SHB_USER_INFO OWN
                     ON OWN.USER_ID = XMXX.CREATE_USER_ID 
                  where 1=1 AND XMXX.COUNTY in ('CQ50011001', 
                                                'CQ50011002')

在这里插入图片描述

-- 优化后执行计划
1   #NSET2: [241, 400, 7740] 
2     #PRJT2: [241, 400, 7740]; exp_num(28), is_atom(FALSE) 
3       #INDEX JOIN LEFT JOIN2: [241, 400, 7740] 
4         #INDEX JOIN LEFT JOIN2: [236, 65, 7740] 
5           #HASH RIGHT JOIN2: [232, 65, 7740]; key_num(1),  KEY(PRO_JSXZ.ITEM_KEY=XMXX.JSXZ)
6             #PRJT2: [0, 8, 144]; exp_num(2), is_atom(FALSE) 
7               #BLKUP2: [0, 8, 144]; IDXFS_DICTIONARY_ITEMS_GROUP_NO(DICTIONARY_ITEMS)
8                 #SSEK2: [0, 8, 144]; scan_type(ASC), IDXFS_DICTIONARY_ITEMS_GROUP_NO(DICTIONARY_ITEMS), scan_range['1009','1009']
9             #HASH LEFT JOIN2: [231, 65, 7596]; key_num(1), partition_keys_num(0)  KEY(XMXX.COUNTY=PRO_COUNTY.ITEM_KEY)
10              #HASH RIGHT SEMI JOIN2: [230, 65, 7452]; n_keys(1)   KEY(DMTEMPVIEW_17743948.colname=XMXX.COUNTY) KEY_NULL_EQU(0)
11                #CONST VALUE LIST: [0, 2, 48]; row_num(2), col_num(1), 
12                #SLCT2: [230, 65, 7452]; XMXX.CODE = EN.PROJECT_CODE
13                  #NEST LOOP INNER JOIN2: [230, 65, 7452]; [with var]
14                    #CSCN2: [0, 1328, 252]; INDEX33560566(ENERGY_AUDIT as EN)
15                    #PRJT2: [0, 1, 7200]; exp_num(20), is_atom(FALSE) 
16                      #SLCT2: [0, 1, 7200]; XX.UTIME = XX.CREATE_TIME  ******* 优化效果点  *******
17                        #PRJT2: [0, 1, 7200]; exp_num(22), is_atom(FALSE) 
18                          #AFUN: [0, 1, 7200]; afun_num(1); partition_num(1)[X.CODE]; order_num(0)  
19                            #SLCT2: [0, 1, 7200]; (X.TYPE = '5' OR X.STATUS = var3)
20                              #BLKUP2: [0, 1, 7200]; SHB_CQCQ_CODE_INDEX(X)
21                                #SSEK2: [0, 1, 7200]; scan_type(ASC), SHB_CQCQ_CODE_INDEX(SHB_CQCQ as X), scan_range[var2,var2]  ******* 优化效果点  *******
22              #PRJT2: [0, 72, 144]; exp_num(2), is_atom(FALSE) 
23                #BLKUP2: [0, 72, 144]; IDXFS_DICTIONARY_ITEMS_GROUP_NO(DICTIONARY_ITEMS)
24                  #SSEK2: [0, 72, 144]; scan_type(ASC), IDXFS_DICTIONARY_ITEMS_GROUP_NO(DICTIONARY_ITEMS), scan_range['1008','1008']
25          #BLKUP2: [4, 1, 0]; INDEX33559823(DE)
26            #SSEK2: [4, 1, 0]; scan_type(ASC), INDEX33559823(DEPARTMENT as DE), scan_range[XMXX.DUTY_DEPARTMENT_ID,XMXX.DUTY_DEPARTMENT_ID]
27        #BLKUP2: [4, 7, 0]; SHB_USER_INFO_USERID_INDEX(OWN)
28          #SSEK2: [4, 7, 0]; scan_type(ASC), SHB_USER_INFO_USERID_INDEX(SHB_USER_INFO as OWN), scan_range[XMXX.CREATE_USER_ID,XMXX.CREATE_USER_ID]

2.3 优化结果

这条复杂SQL在客户项目中运行最为频繁,从原来8秒已经优化到200毫秒,极大缩短响应时间,减轻数据库服务器的压力。
优化工作适可而止,不要强迫搞到极致,白白浪费时间,其他项目还得忙。


3. 优化心得

  • 1. 遇到巨长的SQL不要慌张,学会拆分,缩小范围。
  • 2. 学会总结,有时根本不用ET工具,可以直接从执行计划看出来,或者从SQL中某部分能快速怀疑对位置。
  • 3. SQL等价改写的前提是一定要读懂语义,进行同含义的改写(改写成简单的,不是绝对的,有时反而需要改成复杂的才能优化)。
  • 4. 像我们这些DBA一般搞懂语义改写就不错了,能懂业务逻辑那才是最好的,少走很多弯路(遇到很多开发商可能SQL编写能力参差不齐,也有可能不是很熟悉业务,没办法的事)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/851137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言内存函数详解

内存函数 本章内容主要讲解&#xff1a;memcpy(内存拷贝函数)&#xff0c;memmove(内存移动函数)&#xff0c;memcmp(内存比较函数)的基本作用和模拟实现。 1.内存函数的介绍 1.memcpy函数 void * memcpy ( void * destination, const void * source, size_t num );函数功能…

购物车功能设计与实现。

购物车功能设计与实现 分析购物车业务流程第一个问题&#xff1a;购物车中的商品、促销信息是静态的还是动态获取的&#xff1f;第二个问题&#xff1a;购物车主要存储哪些数据呢&#xff1f;第三个问题&#xff1a;购物车用什么来存数据购物车存储的数据结构是什么样子的埋坑&…

git的日常使用

加入忽略列表&#xff1a;在.gitignore中加入忽略的文件&#xff0c;build/ 表示build文件夹下&#xff0c;*.jar 表示以jar结尾的&#xff0c;用换行符隔开将另一个分支合并到当前分支&#xff1a;git merge xxx冲突出现&#xff0c;可以看看这里&#xff1a;详解Git合并冲突—…

深入探索C++模板:从基础到高级应用

目录 一、 泛型编程 1.1 为什么需要泛型编程&#xff1f; 二、模板 2.1 概念 2.2 函数模板 2.2.1 概念 2.2.2 语法 2.2.3 示例 2.2.4 模板实例化 隐式实例化 显示实例化 2.2.5 模板参数的匹配原则 2.3 类模板 2.3.1 概念 2.3.2 语法 2.3.3 示例 2.3.4 注意事项…

Nacos安装(centos7)

安装版本2.0.2&#xff0c;下载地址 Release 2.0.2 (Jun 11th, 2021) alibaba/nacos GitHub 安装 启动 到bin目录下 sh startup.sh -m standalone 访问http://192.168.23.130:8848/nacos 输入nacos/nacos登入

excel 方框内打钩符号

大写字母 R &#xff0c;字体选择 Wingdings 2

如何识别手机是否有灵动岛(dynamic island)

如何识别手机是否有灵动岛&#xff08;dynamic island&#xff09; 灵动岛是苹果2022年9月推出的iPhone 14 Pro、iPhone 14 Pro Max首次出现&#xff0c;操作系统最低是iOS16.0。带灵动岛的手机在竖屏时顶部工具栏大于等于51像素。 #define isHaveDynamicIsland ({ BOOL isH…

携手区块链技术,踏上可信“双碳”之路 | 研讨会回顾

自中央明确提出碳达峰碳中和的“双碳”目标以来&#xff0c;区块链技术凭借能为碳排放、碳足迹打上可信标签的天赋异禀&#xff0c;引起了政策部门、学术界及产业实践代表们的高度重视。 7月11日&#xff0c;在第33个全国节能宣传周之际、全国低碳日前夕&#xff0c;微众区块链…

【Linux命令行与Shell脚本编程】 第十七章 图形化桌面环境脚本编程

Linux命令行与Shell脚本编程 第十七章 图形化桌面环境脚本编程 文章目录 Linux命令行与Shell脚本编程七.图形化桌面环境脚本编程7.1.创建文本菜单7.1.1.创建菜单布局7.1.2.创建菜单逻辑7.1.3.整合脚本菜单7.1.4.使用select命令 7.2.创建文本窗口部件7.2.1.dialog软件包部件msg…

vue 08 vue-cli,render函数,props,scoped,ref和mixin

01.render函数是vue中的一个特殊的函数&#xff08;有一个默认的函数做参数&#xff0c;是createElement&#xff09;&#xff0c;用来创造html标签和标签中的内容。好处是可以动态的创建html标签 例如&#xff1a; 其中返回的createElement&#xff08;&#xff09;函数有三…

【CHI】(一)基础概念

基于CHI issueF 本章介绍了CHI体系结构和术语。它包含以下部分&#xff1a; 体系结构概述拓扑结构术语事务分类一致性概述组件命名读数据来源 一、CHI架构 CHI架构是一个可扩展的、支持一致性的集线器接口和由多个组件使用的片上互连。根据系统要求的PPA&#xff08;perform…

Android开发实践:Android.mk模板

关于Android NDK开发的文章已经比较多了&#xff0c;我的博客中也分享了很多NDK开发相关经验和技巧&#xff0c;今天简单写了一个 Android.mk 的示例模板&#xff0c;供初学者参考。 本模板主要给大家示例 Android NDK 开发中的如下几个问题&#xff1a; 如何自动添加需要编译…

24届近5年东华大学自动化考研院校分析

今天给大家带来的是东华大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、东华大学 学校简介 东华大学&#xff08;Donghua University&#xff09;&#xff0c;地处上海市&#xff0c;是教育部直属全国重点大学&#xff0c;国家“双一流”、“211工程”建设高校…

动手学DL——MLP多层感知机【深度学习】【PyTorch】

文章目录 4、多层感知机&#xff08; MLP&#xff09;4.1、多层感知机4.1.1、隐层4.1.2、激活函数 σ 4.2、从零实现多层感知机4.3、简单实现多层感知机4.4、模型选择、欠拟合、过拟合4.5、权重衰退4.6、丢失法|暂退法&#xff08;Dropout&#xff09;4.6.1、dropout 函数实现4…

websocket知识点

http协议 http协议特点&#xff1a; 无状态协议每个请求是独立的单双工通信&#xff0c;且服务器无法主动给客户端发信息http协议受浏览器同源策略影响 http实现双向通信方法: 轮询长轮询iframe流sse EventSource websocket协议 websocket协议: 全双工协议支持跨域支持多…

大学生口才培训需求分析

标题&#xff1a;大学生口才培训需求分析 摘要&#xff1a; 本论文旨在分析大学生口才培训的需求&#xff0c;通过对大学生口才培训的重要性、现状和挑战进行研究&#xff0c;并结合相关理论和实践经验&#xff0c;提出相应的培训需求和解决方案。通过本论文的研究&#xff0c…

stm32 cubemx can通讯(1)回环模式

文章目录 前言一、cubemx配置二、代码1.过滤器的配置&#xff08;后续会介绍&#xff09;2.main.c3.主循环 总结 前言 介绍使用stm32cubemx来配置can&#xff0c;本节讲解一个简答&#xff0c;不需要stm32的can和外部连接&#xff0c;直接可以用于验证的回环模式。 所谓回环模…

Redis数据库学习

目录 第一章、Redis数据库的下载和安装1.1&#xff09;nosql数据库和 Redis 介绍1.2&#xff09;Windows中下载安装Redis数据库1.3&#xff09;Linux中安装Redis数据库1.4&#xff09;Linux中启动redis1.4&#xff09;Linux中关闭redis 第二章、三种Redis客户端连接Redis数据库…

TS 踩坑之路(四)之 Vue3

一、在使用定义默认值withDefaults和defineProps 组合时&#xff0c;默认值设置报错 代码案例 报错信息 不能将类型“{ isBackBtn: false; }”分配给类型“(props: PropsType) > RouteMsgType”。 对象字面量只能指定已知属性&#xff0c;并且“isBackBtn”不在类型“(pro…