前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FF010-参数优化案例 : 数据库升级后的SQL不仅慢, 还耗尽了temp表空间, 考验DBA的时刻来了!

FF010-参数优化案例 : 数据库升级后的SQL不仅慢, 还耗尽了temp表空间, 考验DBA的时刻来了!

作者头像
老虎刘
发布2024-07-19 19:01:56
740
发布2024-07-19 19:01:56
举报
文章被收录于专栏:老虎刘谈oracle性能优化

上篇文章FF009的SQL_text有一处符号错误, 有学员发现, 已修正, 并奖励学员大红包一个.

今天的这种案例, 处理时间可能花一小时, 但是写出来能让人看懂并印象深刻, 我至少要花一上午(包括制作test case给大家自己动手重现故障现象). 如果没有付费阅读, 可能大家看不到这篇文章.

我曾经把这个案例优化前后的SQL monitor文件发到200多人的学员群让他们分析, 没有人告诉我到底是哪里做了优化.

还有两个学员也问过我类似的问题, 其中一个还引出了一篇关于性能优化方法论的文章, 更让我印象深刻, 文末有截图.

下面开始正题.

客户的数据库从11g升级到了12.1后(升级到19c也是一样), 原来执行不到2分钟的SQL, 执行了9个多小时还没有结束. 我的同事在现场,这么复杂的SQL一时半会他也没有头绪, 于是收集了sqlhc向我求助.

SQL很复杂, 包含了很多的写法特征:

标量子查询(聚合,case when+聚合,不带聚合等多种形式), connect by, not in , union ,not exists(带rownum), 分页 等, sql_text 如下所示:

代码语言:javascript
复制
SELECT *  from 
( select temp.*, rownum tmp_row_no 
from 
( select 
        s.client_code 委托方编码,
        s.client_name 委托方,
        t.service_order_no 服务单号,
        t.contact_time 接入时间,
        (select v.code_name  from sup.sys_codelist_slave v  where v.parentid='155' and v.code_value=t.order_origin) 单据来源,
        t.branch_code 中心编码,
        (select c.branch_name from sup.sup_branch c where t.org_code=c.org_code and t.branch_code=c.branch_code) 中心名称,
        (select c.zone_name  from sup.sup_branch c where t.org_code=c.org_code and t.branch_code=c.branch_code) 片区,
        t.unit_code 网点编码,
        t.unit_name 网点名称,
        t.settlement_unit_code 结算网点编码,
        t.settlement_unit_name 结算网点名称,
        t.implement_main_type_name 实施业务类型,
        (select v.code_name  from sup.sys_codelist_slave v  where v.parentid='229' and v.code_value=t.customer_level) 用户级别,
        s.prod_name 品类,
        s.brand_name 品牌,
        t.finish_time 服务完成时间,
        t.service_finish_time 工单完成时间,
        t.appoint_start_time 首约开始时间,
        t.appoint_end_time 首约结束时间,
        case when a.change_appoint_time is not null then a.appoint_start_time end 改约开始时间,
        (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) 到达时间,
        t.service_method_name 服务方式,
        a.engineer_code 工程师编码,
        a.engineer_name 工程师名称,
        t.feedback_desc  反馈描述,
        t.feedback_main_item_name 网点一级反馈,
        t.feedback_sub_item_name 网点二级反馈,
        (select v.code_name from sup.sys_codelist_slave v where v.parentid='234' and v.code_value=a.feedback_result_code)  工程师反馈结果,
        a.feedback_main_item_name 工程师一级反馈,
        a.feedback_sub_item_name 工程师二级反馈,
        case when (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) 
          between (t.appoint_start_time-1/24) and t.appoint_end_time 
          and  (nvl(t.finish_time,t.service_finish_time)-
        (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 <=24 
        then '1' else '0' end 快准
        ,case when (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no)
          between (t.appoint_start_time-1/24) and t.appoint_end_time 
          and  (nvl(t.finish_time,t.service_finish_time)-
          (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 >24
          and  (nvl(t.finish_time,t.service_finish_time)-
         (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 <120 
         then '1' else '0' end 不快准
        ,case when ((select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no)
          not between (t.appoint_start_time-1/24) and t.appoint_end_time) 
          and  (nvl(t.finish_time,t.service_finish_time)-
        (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 <=24 then '1'
          when (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) is null 
            and (nvl(t.finish_time,t.service_finish_time)-nvl(t.appoint_end_time,t.contact_time))*24 <=24
          then '1'  else '0' end 快不准
       ,case when  ((select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) 
          not between (t.appoint_start_time-1/24) and t.appoint_end_time)
        and (nvl(t.finish_time,t.service_finish_time)-
        (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 >24  
        and (nvl(t.finish_time,t.service_finish_time)-
        (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 <=120 then '1' 
        when (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) is null
          and (nvl(t.finish_time,t.service_finish_time)-nvl(t.appoint_end_time,t.contact_time))*24 >24 
          and (nvl(t.finish_time,t.service_finish_time)-nvl(t.appoint_end_time,t.contact_time))*24 <=120  then '1'
          else '0' end 不快不准
        ,case when ((select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no)  
          between (t.appoint_start_time-1/24) and t.appoint_end_time) and (nvl(t.finish_time,t.service_finish_time)-
         (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 >120 then '1' 
          when ((select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no)
            not between (t.appoint_start_time-1/24) and t.appoint_end_time) and (nvl(t.finish_time,t.service_finish_time)-
         (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no))*24 >120 then '1'
          when (select min(c.on_site_time) from wom.wom_dispatch_order c where c.service_order_no=t.service_order_no) is null 
          and  (nvl(t.finish_time,t.service_finish_time)-nvl(t.appoint_end_time,t.contact_time))*24 >120 then '1'
            when nvl(t.finish_time,t.service_finish_time) is null 
               and (sysdate-nvl(nvl(a.appoint_end_time,t.appoint_end_time),t.contact_time))*24 >120  then '1'
          else '0' end 超五
from wom.wom_service_order t
join wom.wom_service_user_demand s on t.org_code=s.org_code and t.service_order_no=s.service_order_no and s.pub_validly='Y'
join wom.wom_dispatch_order a     
 on s.dispatch_order_id=a.dispatch_order_id  and a.pub_validly='Y'
where  t.pub_validly='Y'
    and t.order_origin not in ('11','26','30','49','25','29','36','50','34','31','54','39','21')
    and s.brand_code not in ('RONGSHIDA', 'DAMINI')
    and nvl(t.unit_code, '0') != 'W1101100059'
    and not (nvl(t.settlement_unit_name, '0') like '%苏宁%' and s.org_code = 'CS006')
    and t.service_method_code='10'
    and t.implement_main_type_code in ('10','11','13','19')
    and s.prod_code not in 
    (select pr.prod_code from sup.sup_prod_type pr
        start with pr.prod_code in ('16', '118')
        connect by prior pr.prod_code = pr.parent_node_id 
        union
     select '1022' from dual
    )
    and t.service_order_status<>'22'
    and not exists 
    (select * from 
        (select * from wom.wom_feedback_info fi
        where fi.dispatch_order_id = a.dispatch_order_id
            and a.on_site_time is null
            and (fi.feedback_result_code in ('12', '13') or fi.feedback_sub_item_code in ('FW0103', 'FW0104'))
        order by fi.feedback_time
        ) fiTmp
    where rownum <= 1
    and fiTmp.feedback_time <t.appoint_end_time
    )
    and a.dispatch_order_id not in 
        (
        select c.dispatch_order_id 
        from wom.wom_dispatch_order c  
        where c.service_order_no = a.service_order_no
            and c.dispatch_order_status = '17'
            and c.pub_validly = 'Y'
            and c.on_site_time is null
            and c.pub_modi_date < t.appoint_end_time
        )
     and s.client_code in ('CL000001') 
     and  t.pub_create_date >= to_date(' 2021-09-21 00:00:00','yyyy-mm-dd hh24:mi:ss') 
     and  t.pub_create_date <= to_date(' 2021-09-21 23:59:59','yyyy-mm-dd hh24:mi:ss')
     and t.org_code = :1   
 )  temp where rownum <= 500000
) where tmp_row_no > 0
;

优化前的执行计划(执行计划太长,只截取了关键部分,未付费用户有兴趣也可加v获取原始文件):

优化前后的两个sql monitor文件,我会放到答疑群.

优化后的执行计划:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老虎刘谈oracle性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档