MySQL跟OB 执行SQL效率对比

【 使用环境 】生产环境
【 OB or 其他组件 】OBCE-4.2.2
【 使用版本 】OBCE-4.2.2
【问题描述】同一条SQL 在mysql 跟OB 执行差距很大,
【复现路径】问题出现前后相关操作

select /*+ORDERED  full(sp)  */
  distinct wo.wo_id,
  (
    case
    when wo.type = 2 then '维护工单'
    else '工单'
    end
  ) as wo_type,
  wo.wo_code,
  wo.request_name,
  wo.request_phone,
  wo.location,
  wo.wo_desc,
  wo.payment_item_num,
  (
    case wo.`status`
    when 0 then '已创建'
    when 1 then '已派工'
    when 2 then '处理中'
    when 3 then '已暂停'
    when 4 then '已终止'
    when 5 then '已完成'
    when 6 then '已验证'
    when 7 then '已存档'
    when 8 then '待审批'
    end
  ) as wo_status,
  wo.created_date,
  wo.actual_arrival_datetime,
  wo.actual_completion_datetime,
  wo.estimated_arrival_datetime,
  wo.estimated_completion_datetime,
  wo.work_content,
  servicetyp3_.full_name as stfullname,
  priority1_.priority_name,
  (
    case sp.proj_name
    when '工程中心SC' then 'SC1'
    when '储能HQ1' then 'HQ1'
    when '创新21C' then '21C'
    else sp.proj_name
    end
  ) as projectname,
  tc.value as actual_working_time,
  (
    case tc.unit
    when 3 then '秒'
    when 4 then '分钟'
    when 5 then '小时'
    when 6 then '天'
    end
  ) as actual_working_value,
  tc2.value as estimated_working_time,
  (
    case tc2.unit
    when 3 then '秒'
    when 4 then '分钟'
    when 5 then '小时'
    when 6 then '天'
    end
  ) as estimated_working_value,
  tc3.value as stop_time,
  (
    case tc3.unit
    when 3 then '秒'
    when 4 then '分钟'
    when 5 then '小时'
    when 6 then '天'
    end
  ) as stop_time_value,
  employee2_.em_name,
  workorderl1_.actual_working_time * 60 as em_work_time,
  workorderl1_.responsible,
  (
    case period.type
    when 0 then '年度'
    when 1 then '季度'
    when 2 then '月度'
    when 3 then '周'
    when 4 then '天'
    end
  ) as periodType,
  wo.modified_date,
  (
    case workorderl1_.status
    when 0 then '未接单'
    when 1 then '已接单'
    when 2 then '已退单'
    when 3 then '已提交'
    end
  ) as work_status,
  b.finished_status,
  b.file_hash_status
from
  wo
  left join priority priority1_ on wo.priority_id = priority1_.priority_id
  left join wo_laborer workorderl1_ on wo.wo_id = workorderl1_.wo_id
  left join em employee2_ on workorderl1_.laborer_id = employee2_.em_id
  left join service_type servicetyp3_ on wo.stype_id = servicetyp3_.stype_id
  left join sys_project sp on wo.proj_id = sp.proj_id
  left join em_info_project eif on employee2_.em_id = eif.em_id
  left join time_count tc on wo.actual_working_time = tc.time_count_id  and tc.unit = 4
  left join time_count tc2 on wo.estimated_working_time = tc2.time_count_id
  left join time_count tc3 on wo.stop_time = tc3.time_count_id  and tc.unit = 4
  left join pm on wo.pm_id = pm.pm_id
  left join period on period.period_id = pm.period_id
  left join (
    select
      group_concat(
        con
        order by
          con separator '|'
      ) as finished_status,
      group_concat(fm_file_hash) as file_hash_status,
      wo_id
    from
      (
        select
          concat_ws(
            ';',
            ps.sort,
            ps.comment,(
              case ps.finished
              when 0 then '未完成'
              when 1 then '已完成'
              end
            )
          ) as con,
          psf.fm_file_hash fm_file_hash,
          wo_id,
          ps.sort
        from
          pm_step ps
          left join pm_step_file psf on ps.pm_step_id = psf.pm_step_id
      ) a
    group by
      a.wo_id
  ) b on wo.wo_id = b.wo_id
where
  wo.deleted = 0
  and sp.deleted = 0
  and sp.proj_name != 'DEMO'
  and wo.created_date > '2024-7-1'
order by
  created_date

OB执行计划:
执行 70s

MySQL 执行计划:
MySQL 执行 9s

1 个赞
===============================================================================================
|ID|OPERATOR                                        |NAME               |EST.ROWS|EST.TIME(us)|
-----------------------------------------------------------------------------------------------
|0 |SORT                                            |                   |196806  |4888933     |
|1 |└─HASH DISTINCT                                 |                   |196806  |4520133     |
|2 |  └─HASH RIGHT OUTER JOIN                       |                   |196806  |4143987     |
|3 |    ├─SUBPLAN SCAN                              |b                  |322917  |1288812     |
|4 |    │ └─MERGE GROUP BY                          |                   |322917  |1287957     |
|5 |    │   └─PARTITION SORT                        |                   |2198145 |1116898     |
|6 |    │     └─MERGE RIGHT OUTER JOIN              |                   |2198145 |416748      |
|7 |    │       ├─TABLE FULL SCAN                   |psf(idx01)         |691859  |36703       |
|8 |    │       └─TABLE FULL SCAN                   |ps(idx02)          |2198145 |252524      |
|9 |    └─HASH RIGHT OUTER JOIN                     |                   |130075  |2686518     |
|10|      ├─TABLE FULL SCAN                         |eif(eip_ei_idx)    |53      |6           |
|11|      └─HASH RIGHT OUTER JOIN                   |                   |130075  |2675564     |
|12|        ├─TABLE FULL SCAN                       |employee2_(idx01)  |4168    |205         |
|13|        └─HASH OUTER JOIN                       |                   |129669  |2659601     |
|14|          ├─HASH RIGHT OUTER JOIN               |                   |107394  |2273460     |
|15|          │ ├─TABLE FULL SCAN                   |period             |143526  |8341        |
|16|          │ └─HASH OUTER JOIN                   |                   |107237  |2222042     |
|17|          │   ├─HASH OUTER JOIN                 |                   |107237  |1544851     |
|18|          │   │ ├─HASH OUTER JOIN               |                   |107237  |870008      |
|19|          │   │ │ ├─HASH JOIN                   |                   |107237  |162411      |
|20|          │   │ │ │ ├─TABLE FULL SCAN           |sp(idx01)          |60      |11          |
|21|          │   │ │ │ └─HASH RIGHT OUTER JOIN     |                   |107237  |150110      |
|22|          │   │ │ │   ├─TABLE FULL SCAN         |pm                 |73175   |4329        |
|23|          │   │ │ │   └─HASH RIGHT OUTER JOIN   |                   |107237  |119556      |
|24|          │   │ │ │     ├─TABLE FULL SCAN       |servicetyp3_(idx01)|941     |53          |
|25|          │   │ │ │     └─HASH RIGHT OUTER JOIN |                   |107237  |107985      |
|26|          │   │ │ │       ├─TABLE FULL SCAN     |priority1_(idx01)  |226     |15          |
|27|          │   │ │ │       └─TABLE FULL SCAN     |wo                 |107237  |96631       |
|28|          │   │ │ └─TABLE FULL SCAN             |tc                 |2717332 |347767      |
|29|          │   │ └─TABLE FULL SCAN               |tc2                |3277046 |263675      |
|30|          │   └─TABLE FULL SCAN                 |tc3                |3277046 |263675      |
|31|          └─TABLE FULL SCAN                     |workorderl1_(idx01)|1165004 |140375      |
===============================================================================================

image
image

表 time_count 有300+万数据,呗扫描了3次,通过改写with tcc as ( select /+MATERIALIZE/ * from time_count) , 缓存 临时表,减少扫描次数 ,看执行计划 也正常,


但是效率更低了,这是为啥?

统计信息准确吗,还有就是就是执行计划表驱动顺序和MySQL好像不一致,可以先用Hint搞成和MySQL一致的看看效果
其次看执行计划没有走上分区并行,搞成分区表说不定要好点

当时遇到性能问题,第一时间 收集了统计信息。这几张不是分区表,害怕分布式执行计划特意绑了表组。
我按照mysql 的 表顺序 丙丁了hint ,也不行,很慢。
看来 这是优化器底层的差异。

主要这个SQL也复杂表也多,改造成分区表确实不好搞。。那租户资源合理不内存够不够,预估出来其实也才几秒,执行几十秒差距还是挺大
可以用dbms_xplan.display_cursor看看真实的执行计划和对应的耗时,会不会有中间结果集转储到磁盘中的情况

用obdiag 巡检这表信息
obdiag gather scene run --scene=observer.perf_sql --env “{db_connect=’-hxx -Pxx -uxx -pxx -Dxx’, trace_id=‘xx’}”
obdiag文档
https://www.oceanbase.com/docs/common-obdiag-cn-1000000001102504

先通过 DBMS_XPLAN.DISPLAY_CURSOR 看下计划里各个算子的优化器估行和真实行数差距大不大?

详见:https://oceanbase.yuque.com/org-wiki-obtech-vh7w9r/notes/iafst03225nacdpy#bMgXS 中的 “确定 Outline 创建生效” 部分。