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主要的开销在哪里?而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制文件 ...
随机推荐
- Element-ui源码解析(一):项目目录解析
开始看原码了,我们要开始一些准备工作, 既然是拆代码,那么我们要先把代码搞到手 1.如何下载原码 随便开个项目 npm i element-ui -S 将源码下载到本地 随后在node_module ...
- Nginx:超时 keeplive_timeout 配置
参考:Nginx的超时keeplive_timeout配置详解 HTTP 是一种无状态协议,客户端向服务器发送一个 TCP 请求,服务端响应完毕后断开连接. 如果客户端向服务器发送多个请求,每个请求都 ...
- jsp中的一些问题
jsp里的${pageContext.request.contextPath} 在JSP中,${pageContext.request.contextPath}是一个EL表达式(Expression ...
- Flutter系列文章-Flutter进阶2
这一节我将再详细地为您介绍 Flutter 进阶主题,包括导航和路由.状态管理.异步处理.HTTP请求和Rest API,以及数据持久化.让我们逐个介绍这些主题. 1.导航和路由 在 Flutter ...
- 零基础入门——从零开始学习PHP反序列化笔记(二)
魔术方法 魔术方法介绍 __construct() 触发时机:实例化对象之前 构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法; <?php class User { public ...
- 牛客小白月赛65 D题 题解
原题链接 题意描述 一共有两堆石子,第一堆有 \(a\) 个,第二堆有 \(b\) 个,牛牛和牛妹轮流取石子,牛牛先手,每次取石子的时候只能从以下 \(2\) 种方案种挑一种来取(对于选择的方案数必须 ...
- Spring Boot 最佳实践
本文翻译自国外论坛 medium,原文地址:https://medium.com/@raviyasas/spring-boot-best-practices-for-developers-3f3bdf ...
- dimp V8:[WARNING]login fail, check your username and password, and check the server status
在进行某个项目的性能测试时,我们选择了达梦8作为使用的数据库.因前期的网络安全问题和考虑到节省成本,我们首先在公司本地服务器上搭建了相应的环境,并生成了用于压力测试的业务数据. 然而,在将数据库迁移到 ...
- React-Chat移动端聊天实例|react18 hooks仿微信App聊天界面
基于react18+react-vant+zustand仿微信手机端聊天室ReactChat. react18-chat 一款使用最新react18.x hooks.zustand搭配react-va ...
- 【Qt6】工具提示以及调色板设置
工具提示即 Tool Tip,当用户把鼠标移动到某个UI对象上并悬停片刻,就会出现一个"短小精悍"的窗口,显示一些说明性文本.一般就是功能描述,让用户知道这个XX是干啥用的. 在 ...