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主要的开销在哪里?而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制文件 ...
随机推荐
- C++之函数的分文件编写
从黑马程序员的c++课里学到的函数的分文件编写 函数的分文件编写 作用:让代码结构更加清晰 函数分文件编写一般有4个步骤 1,创建后缀名为.h的头文件 2,创建后缀名为.cpp的源文件 3,在头文件中 ...
- MIT 6.5840 Raft Implementation(2B, Log Replication)
Raft实现思路+细节(2B) 任务分解 2B中最主要的任务就是进行日志的复制.Raft是一个强领导人的系统,这意味着所有的日志添加都是由领导人发起的,与之相类似的,还有很多其他的结论(它们都是比较显 ...
- 【Azure Event Hub】Event Hub的Process Data页面无法通过JSON格式预览数据
问题描述 在Event Hub的门户页面中,可以通过Process Data页面查看Event Hub中的数据,但是当使用JSON格式预览时(View in JSON),却出现错误. 消息一: No ...
- netstat 某连接的 Recv-Q(接收队列)达到500多万字节的内核参数排查
思路: cat proc文件系统下的 sys/net 目录下所有文件,根据结果降序排序(如果打印前xx,可能会漏掉关键信息,在定位问题时需要注意,慎用过滤),根据结果使用 grep -rn xxx 找 ...
- Vue报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location
错误原因,我猜测多半是版本问题 在router/index.js中添加如下代码 const originalPush = VueRouter.prototype.push VueRouter.prot ...
- ABC295 D题 题解
题意简述 给定一个长度不超过\(\;5\times 10^5\;\)的,仅有数字构成的字符串,问存在多少段子串,使得子串内字符重新排序后,前半段与后半段相同? 做法分析 重组后前后两部分相同,其实也就 ...
- 聚焦Web前端安全:最新揭秘漏洞防御方法
在 Web 安全中,服务端一直扮演着十分重要的角色.然而前端的问题也不容小觑,它也会导致信息泄露等诸如此类的问题.在这篇文章中,我们将向读者介绍如何防范Web前端中的各种漏洞.[万字长文,请先收藏再阅 ...
- Ubuntu关机卡死解决办法
sync && sudo syncsudo shutdwon -h now
- 角度新奇!第一次看到这样使用MyBatis的,看得我一愣一愣的。
你好呀,我是歪歪. 这期给大家分享一个读者给我分享的一个关于 MyBatis 的"编程小技巧",说真的,这骚操作,直接把我看得一愣一愣的. 我更情愿叫它:坑你没商量之埋雷大法. D ...
- 数据库中limit 和 offset 使用区别
题:查找最晚入职员工的所有信息 1,SELECT * FROM employees ORDER BY hire_date DESC LIMIT 0,1; 解:对列hire_date分组后升序,从下标( ...