oceanbase 数据库SQL优化 (把你的脑袋当成CBO)

OB一哥们找我优化条SQL,反馈在OceanBase存储过程执行时间很慢,需要626秒才能出结果,安排。
INSERT INTO insurance_stat_sx
(id,
stat_date,
cal_num,
underwrite_num,
veh_num,
effect_num,
effect_money,
unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type)
SELECT t_seq_common.nextval AS id,
'2023-05-15',
cal_num,
underwrite_num,
veh_num,
effect_num,
effect_money,
unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM (SELECT SUM(cal_num) AS cal_num,
SUM(underwrite_num) AS underwrite_num,
SUM(veh_num) AS veh_num,
SUM(effect_num) AS effect_num,
SUM(effect_money) AS effect_money,
unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM (SELECT log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
SUM(CASE
WHEN log.oper_type = 2 THEN
1
ELSE
0
END) cal_num,
SUM(CASE
WHEN log.oper_type = 3 THEN
1
ELSE
0
END) underwrite_num,
COUNT(DISTINCT(registration_number)) veh_num,
0 effect_num,
0 effect_money,
log.client_type,
log.app_type
FROM AAAAA log
WHERE log.life_agent_id IS NOT NULL
AND log.create_time >=
TO_DATE('2023-05-15', 'yyyy-mm-dd')
AND log.create_time <
TO_DATE('2023-05-16', 'yyyy-mm-dd')
AND log.app_type IS NOT NULL
AND log.client_type IS NOT NULL
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type
UNION ALL
SELECT log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
0 cal_num,
0 underwrite_num,
0 veh_num,
COUNT(p.BBBB_pk) effect_num,
SUM(NVL(po.underwritten_premium, 0)) effect_money,
log.client_type,
log.app_type
FROM BBBB p,
CCCC v,
DDDD pr,
EEEE po,
(SELECT unit_code,
policy_id,
TO_CHAR(create_time, 'yyyy-mm-dd') create_time,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM AAAAA
WHERE policy_status = '3'
AND oper_type = 7
AND life_agent_id IS NOT NULL
AND app_type IS NOT NULL
AND client_type IS NOT NULL
GROUP BY unit_code,
policy_id,
TO_CHAR(create_time, 'yyyy-mm-dd'),
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type) log
WHERE p.BBBB_pk = v.BBBB_fk
AND v.CCCC_pk = pr.CCCC_fk
AND pr.DDDD_pk = po.DDDD_fk
AND p.policy_status = '3'
AND log.policy_id = p.BBBB_pk
AND log.create_time >= '2023-05-15'
AND log.create_time < '2023-05-16'
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type)
GROUP BY unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type) tmp;
SQL整体返回0行数据,所以insert into 也是0行,insurance_log 表 12亿行数据。
当时OB哥们给到我的时候我再忙其他事情,没有要执行计划,粗略扫了一下SQL大致的写法。
得知了 AAAAA 表 12 亿行数据以后,让他加个并行hint 试试看速度。
下面SQL除了加了并行 HINT ,后面无任何修改。
select /*+ USE_PX PARALLEL(8)*/
t_seq_common.nextval as id,
--to_char('2023-05-15', 'yyyy-mm-dd') as stat_date,
'2023-05-15',
cal_num,
underwrite_num,
veh_num,
effect_num,
effect_money,
unit_code,
life_agent_id,
life_agent_name... 省略后面SQL

并行 hint 加完以后只需要 281s 就能出结果,当时我也忙其他事情,没继续优化下去。
但是这哥们领导不依不饶,还得继续让他优化,没办法只能帮忙仔细看看了。

缓慢节点:
SELECT log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
SUM(CASE
WHEN log.oper_type = 2 THEN
1
ELSE
0
END) cal_num,
SUM(CASE
WHEN log.oper_type = 3 THEN
1
ELSE
0
END) underwrite_num,
COUNT(DISTINCT(registration_number)) veh_num,
0 effect_num,
0 effect_money,
log.client_type,
log.app_type
FROM AAAAA log
WHERE log.life_agent_id IS NOT NULL
AND log.create_time >=
TO_DATE('2023-05-15', 'yyyy-mm-dd')
AND log.create_time <
TO_DATE('2023-05-16', 'yyyy-mm-dd')
AND log.app_type IS NOT NULL
AND log.client_type IS NOT NULL
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type
UNION ALL SELECT log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
0 cal_num,
0 underwrite_num,
0 veh_num,
COUNT(p.BBBB_pk) effect_num,
SUM(NVL(po.underwritten_premium, 0)) effect_money,
log.client_type,
log.app_type
FROM BBBB p,
CCCC v,
DDDD pr,
EEEE po,
(SELECT unit_code,
policy_id,
TO_CHAR(create_time, 'yyyy-mm-dd') create_time,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM AAAAA
WHERE policy_status = '3'
AND oper_type = 7
AND life_agent_id IS NOT NULL
AND app_type IS NOT NULL
AND client_type IS NOT NULL
GROUP BY unit_code,
policy_id,
TO_CHAR(create_time, 'yyyy-mm-dd'),
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type) log
WHERE p.BBBB_pk = v.BBBB_fk
AND v.CCCC_pk = pr.CCCC_fk
AND pr.DDDD_pk = po.DDDD_fk
AND p.policy_status = '3'
AND log.policy_id = p.BBBB_pk
AND log.create_time >= '2023-05-15'
AND log.create_time < '2023-05-16'
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type;
union all 上面这段SQL AAAAA 表12亿数据,返回0行。
union all 下面这段SQL BBBB p 1.9亿、CCCC v 1.9亿 、DDDD pr 2.7亿、EEEE po 4430万、log 内联视图 2025W,关联后返回0行。
这么大的数据量关联,慢也是正常,但是知道数据量以后就好办了。
SQL改写 + hint 干预方案 :
SELECT t_seq_common.nextval AS id,
--to_char('2023-05-15', 'yyyy-mm-dd') as stat_date,
'2023-05-15',
cal_num,
underwrite_num,
veh_num,
effect_num,
effect_money,
unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM (SELECT SUM(cal_num) AS cal_num,
SUM(underwrite_num) AS underwrite_num,
SUM(veh_num) AS veh_num,
SUM(effect_num) AS effect_num,
SUM(effect_money) AS effect_money,
unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM (WITH x_log AS (
SELECT /*+ USE_PX PARALLEL(6)*/ *
FROM AAAAA log
WHERE log.life_agent_id IS NOT NULL
AND log.app_type IS NOT NULL
AND log.client_type IS NOT NULL
AND log.create_time >= to_date('2023-05-15', 'yyyy-mm-dd')
AND log.create_time < to_date('2023-05-16', 'yyyy-mm-dd')
)
SELECT /*+ USE_PX PARALLEL(4)*/
* log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
SUM(CASE
WHEN log.oper_type = 2 THEN
1
ELSE
0
END) cal_num,
SUM(CASE
WHEN log.oper_type = 3 THEN
1
ELSE
0
END) underwrite_num,
COUNT(DISTINCT(registration_number)) veh_num,
0 effect_num,
0 effect_money,
log.client_type,
log.app_type
FROM x_log log
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type
UNION ALL
SELECT /*+
MERGE(log)
USE_PX PARALLEL(5)
PQ_DISTRIBUTE(p hash, hash)
PQ_DISTRIBUTE(v hash, hash)
PQ_DISTRIBUTE(pr hash, hash)
PQ_DISTRIBUTE(po hash, hash)
PQ_DISTRIBUTE(log hash, hash)
*/
log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
0 cal_num,
0 underwrite_num,
0 veh_num,
COUNT(p.BBBB_pk) effect_num,
SUM(nvl(po.underwritten_premium, 0)) effect_money,
log.client_type,
log.app_type
FROM BBBB p,
CCCC v,
DDDD pr,
EEEE po,
(SELECT /*+ USE_PX PARALLEL(5)*/
unit_code,
policy_id,
to_char(create_time, 'yyyy-mm-dd') create_time,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
FROM x_log log
WHERE policy_status = '3'
AND oper_type = 7
GROUP BY unit_code,
policy_id,
to_char(create_time, 'yyyy-mm-dd'),
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type) log
WHERE p.BBBB_pk = v.BBBB_fk
AND v.CCCC_pk = pr.CCCC_fk
AND pr.DDDD_pk = po.DDDD_fk
AND p.policy_status = '3'
AND log.policy_id = p.BBBB_pk
GROUP BY log.unit_code,
log.life_agent_id,
log.life_agent_name,
log.sx_unit_code,
log.sx_unit_name,
log.sx_dept_group_code,
log.sx_dept_group_name,
log.sx_branch_code,
log.sx_branch_name,
log.unit_name,
log.dept_group_code,
log.dept_group_name,
log.dept_code,
log.dept_name,
log.section_code,
log.section_name,
log.client_type,
log.app_type)
GROUP BY unit_code,
life_agent_id,
life_agent_name,
sx_unit_code,
sx_unit_name,
sx_dept_group_code,
sx_dept_group_name,
sx_branch_code,
sx_branch_name,
unit_name,
dept_group_code,
dept_group_name,
dept_code,
dept_name,
section_code,
section_name,
client_type,
app_type
) tmp;
最终上面SQL 27s 就能跑出结果。

这个案例从始至终没有看过执行计划 (OB的执行计划我也看不懂,看了也是白看)。
当具备一定优化理论知识之后,我们可以不看执行计划,直接根据 SQL 写法和表的数据量来判断是否走 NL 还是 HASH,
然后一直这样进行下去直到 SQL 语句中所有表都关联完毕,如果大家长期采用此方法进行锻炼,久而久之,你自己的脑袋就是 CBO。
oceanbase 数据库SQL优化 (把你的脑袋当成CBO)的更多相关文章
- 我的mysql数据库sql优化原则
原文 我的mysql数据库sql优化原则 一.前提 这里的原则 只是针对mysql数据库,其他的数据库 某些是殊途同归,某些还是存在差异.我总结的也是mysql普遍的规则,对于某些特殊情况得特殊对待. ...
- 数据库sql优化方案
声明:这个不是我自己写的,是我们老师给我,我拿出来分享一下! 为什么要优化: 随着实际项目的启动,数据库经过一段时间的运行,最初的数据库设置,会与实际数据库运行性能会有一些差异,这时我们 ...
- SQL优化- 数据库SQL优化——使用EXIST代替IN
数据库SQL优化——使用EXIST代替IN 1,查询进行优化,应尽量避免全表扫描 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引 . 尝试下面的 ...
- 数据库sql优化总结之5--数据库SQL优化大总结
数据库SQL优化大总结 小编最近几天一直未出新技术点,是因为小编在忙着总结整理数据库的一些优化方案,特此奉上,优化总结较多,建议分段去消化,一口吃不成pang(胖)纸 一.百万级数据库优化方案 1.对 ...
- 数据库SQL优化大总结之百万级数据库优化方案
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- (转)数据库SQL优化大总结之 百万级数据库优化方案
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- 数据库 SQL 优化大总结之:百万级数据库优化方案
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- 数据库SQL优化大总结之 百万级数据库优化方案(转载)
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- 数据库SQL优化大总结之百万级数据库优化方案(转)
add by zhj: 作者没有指定是哪个数据库,这只是一个近似通用的总结.对于某个特定的数据库,有些条目可能并不适用. 原文:http://www.cnblogs.com/yunfeifei/p/3 ...
- 关于数据库SQL优化
1.数据库访问优化 要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在哪里?而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制文件 ...
随机推荐
- 利用Redis实现向量相似度搜索:解决文本、图像和音频之间的相似度匹配问题
在自然语言处理领域,有一个常见且重要的任务就是文本相似度搜索.文本相似度搜索是指根据用户输入的一段文本,从数据库中找出与之最相似或最相关的一段或多段文本.它可以应用在很多场景中,例如问答系统.推荐系统 ...
- 关于python pycharm中输出的内容不全的解决办法
import pandas as pd #设置显示的最大列.宽等参数,消除打印不完全中间的省略号 pd.set_option("display.width",1000) #加了这一 ...
- quarkus依赖注入之十一:拦截器高级特性上篇(属性设置和重复使用)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<quarkus依赖注入> ...
- Web通用漏洞--CSRF
Web通用漏洞--CSRF 漏洞简介 CSRF(Cross Site Request Forgery, 跨站请求伪造/客户端请求伪造),即通过伪造访问数据包并制作成网页的形式,使受害者访问伪造网页,同 ...
- Midjourney的一些学习心得:如何高效的图生图
注意本文没有什么长篇大论,全部是自己的学习心得. 心得体会:如何图生图 今天在一篇midjourney看到好图应该怎么抄. 相信经常会看到好图也想要的,但是要么抄不出感觉,要么抄过来把水印也抄了,这一 ...
- 一次Python本地cache不当使用导致的内存泄露
背景 近期一个大版本上线后,Python编写的api主服务使用内存有较明显上升,服务重启后数小时就会触发机器的90%内存占用告警,分析后发现了本地cache不当使用导致的一个内存泄露问题,这里记录一下 ...
- API接口的研发与应用
API(Application Programming Interface,应用程序编程接口)指的是为不同的软件应用程序提供编程接口的一组协议.规则以及工具的集合,以便它们能够互相交互,实现数据通 ...
- 解决SVN死锁问题
svn执行clean up后出现提示:svn cleanup failed–previous operation has not finished; run cleanup if it was int ...
- Dami 基于事件总线的本地过程调用框架(首次发版)
Dami,专为本地多模块之间通讯解耦而设计(尤其是未知模块.隔离模块.领域模块).零依赖,特适合 DDD. 特点 结合 Bus 与 RPC 的概念,可作事件分发,可作接口调用,可作异步响应. 支持事务 ...
- Solution -「SCOI 2016」萌萌哒
Description Link. 给定一个长度为 \(n\) 的数组让你填数,需要满足 \(m\) 个形如 \(([l_{1},r_{1}],[l_{2},r_{2}])\) 的要求,这两个区间填好 ...