OceanBase 金融项目优化案例

领导让我帮忙支持下其他项目的SQL优化工作,呦西,是收集案例的好时机。
下面SQL都是在不能远程的情况下,按照原SQL的逻辑等价改写完成否发给现场同事验证。
案例一
慢SQL,4.32秒:
SELECT MY_.*, RM
FROM (SELECT ROWNUM RM, V_.*
FROM (SELECT *
FROM (select count(1) processidnum,
t.processid,
t.proc_name_ as procname
FROM tkdkdkdk t
WHERE 1 = 1
and (t.ASSIGNEE_ = 'server' or exists(select 1
FROM pepepep p
WHERE p.task_ = t.ID_
and (p.agent_userid_ = 'server' or
(substr(p.groupid_, 6) in
(select role_code
FROM upupupup
WHERE user_code = 'server') or
p.userid_ = 'server'))))
GROUP BY t.processid, t.proc_name_)) V_
WHERE ROWNUM <= 100000) MY_
WHERE RM >= 1;
慢SQL执行计划:

改写优化,445ms:
SELECT *
FROM (SELECT *
FROM (SELECT a.*,
rownum rn
FROM (SELECT count(1) processidnum,
t.processid,
t.proc_name_ AS procname
FROM tkdkdkdk t
LEFT JOIN
(SELECT distinct p.task_
FROM pepepep p
LEFT JOIN
(SELECT role_code
FROM upupupup
WHERE user_code = 'server'
GROUP BY role_code) tsu
ON (substr(p.groupid_, 6) = tsu.role_code)
WHERE (p.agent_userid_ = 'server'
OR (tsu.role_code is NOT null
OR p.userid_ = 'server'))) x
ON t.ID_ = x.task_
WHERE 1 = 1
AND (t.ASSIGNEE_ = 'server'
OR x.task_ is NOT NULL)
GROUP BY t.processid, t.proc_name_) a)
WHERE rownum <= 100000)
WHERE rn >= 1;
改写优化后执行计划:

优化思路:
1、原SQL有很多子查询,可能会导致计划走NL,改成JOIN后让CBO自动判断是否走HASH还是NL。
2、换了个标准的分页框架。
案例二
慢SQL,2.6秒:
SELECT MY_.*, RM
FROM (SELECT ROWNUM RM, V_.*
FROM (SELECT *
FROM (select t.*, t.org_code || '-' || t.org_name as codename
FROM (select tc.*
FROM tgtgtgtg tc
start with TC.ORG_ID = '6000001'
connect by prior ORG_ID = tc.parent_id) t
WHERE org_level <= 3
ORDER BY CASE
WHEN ',' || nvl(null, 'fingard') || ',' like '%,' || ORG_ID || ',%' THEN CASE
WHEN length(nvl(org_order, '')) = '9'
then org_order || ''
else '1' || org_code end
when length(nvl(org_order, '')) = '9' then '99999999' || org_order || ''
else '999999991' || org_code end)) V_
WHERE ROWNUM <= 10) MY_;
WHERE RM >= 1;

改写优化一,3.4秒:
SELECT MY_.*, RM
FROM (SELECT ROWNUM RM, V_.*
FROM (SELECT *
FROM (select a.*, a.org_code || '-' || a.org_name as codename
FROM (WITH t(
lv,
codename,
ORG_ID,
parent_id,
org_order,
org_code,
org_name,
org_level
) AS (SELECT 1 as lv,
tc.org_code || '-' || tc.org_name AS codename,
tc.org_name,
tc.ORG_ID,
tc.parent_id,
tc.org_order,
tc.org_code,
tc.org_level
FROM tgtgtgtg tc
WHERE tc.ORG_ID = '6000001'
UNION ALL
SELECT t.lv + 1,
e.org_code || '-' || e.org_name AS codename,
e.org_name,
e.ORG_ID,
e.parent_id,
e.org_order,
e.org_code,
e.org_level
FROM tgtgtgtg e
INNER JOIN t ON t.ORG_ID = e.parent_id)
SELECT *
FROM t) a
WHERE a.org_level <= 3
ORDER BY CASE
WHEN ',' || nvl(null, 'fingard') || ',' like '%,' || ORG_ID || ',%' THEN CASE
WHEN length(nvl(org_order, '')) = '9'
then org_order || ''
else '1' || org_code end
when length(nvl(org_order, '')) = '9' then '99999999' || org_order || ''
else '999999991' || org_code end)) V_
WHERE ROWNUM <= 10) MY_;
WHERE RM >= 1;

使用CTE递归改写方案在PostgreSQL上是个通用的做法,也能取得比较好的性能效果。
但是在OB上反而效果更差点,NL算子性能不够强,使用NESTED-LOOP JOIN 性能反而没有NESTED-LOOP CONNECT BY 算子好。
OB研发在NESTED-LOOP JOIN算子上还有继续优化的空间。
改写优化二,1.5秒:
既然使用NL性能不够理想的情况下,就要想办法使用HASH来优化SQL整体的执行效率。
将自动递归的方式改成手动。
1、首先需要知道数据整体的层级有多少。
SELECT DISTINCT lv
FROM (SELECT level lv
FROM tgtgtgtg tc
START WITH TC.ORG_ID = '6000001'
CONNECT BY PRIOR ORG_ID = tc.parent_id) t;

2、了解到整体的数据是13层,然后使用self join 将不同层级的数据关联起来。
SELECT *
FROM (SELECT *
FROM (SELECT a.*, rownum rn
FROM (SELECT x.*
FROM (WITH tgtgtgtg AS
(SELECT org_code, org_name, org_id, parent_id, org_order, org_level
FROM tgtgtgtg) SELECT 1 AS lv,
v1.org_code || '-' || v1.org_name AS codename,
v1.ORG_ID,
v1.parent_id,
v1.org_order,
v1.org_code,
v1.org_level
FROM tgtgtgtg v1
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 2 AS lv,
v2.org_code || '-' || v2.org_name AS codename,
v2.ORG_ID,
v2.parent_id,
v2.org_order,
v2.org_code,
v2.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 3 AS lv,
v3.org_code || '-' || v3.org_name AS codename,
v3.ORG_ID,
v3.parent_id,
v3.org_order,
v3.org_code,
v3.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 4 AS lv,
v4.org_code || '-' || v4.org_name AS codename,
v4.ORG_ID,
v4.parent_id,
v4.org_order,
v4.org_code,
v4.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 5 AS lv,
v5.org_code || '-' || v5.org_name AS codename,
v5.ORG_ID,
v5.parent_id,
v5.org_order,
v5.org_code,
v5.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 6 AS lv,
v6.org_code || '-' || v6.org_name AS codename,
v6.ORG_ID,
v6.parent_id,
v6.org_order,
v6.org_code,
v6.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 7 AS lv,
v7.org_code || '-' || v7.org_name AS codename,
v7.ORG_ID,
v7.parent_id,
v7.org_order,
v7.org_code,
v7.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 8 AS lv,
v8.org_code || '-' || v8.org_name AS codename,
v8.ORG_ID,
v8.parent_id,
v8.org_order,
v8.org_code,
v8.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 9 AS lv,
v9.org_code || '-' || v9.org_name AS codename,
v9.ORG_ID,
v9.parent_id,
v9.org_order,
v9.org_code,
v9.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 10 AS lv,
v10.org_code || '-' || v10.org_name AS codename,
v10.ORG_ID,
v10.parent_id,
v10.org_order,
v10.org_code,
v10.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 11 AS lv,
v11.org_code || '-' || v11.org_name AS codename,
v11.ORG_ID,
v11.parent_id,
v11.org_order,
v11.org_code,
v11.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 12 AS lv,
v12.org_code || '-' || v12.org_name AS codename,
v12.ORG_ID,
v12.parent_id,
v12.org_order,
v12.org_code,
v12.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
JOIN tgtgtgtg v12 ON v11.ORG_ID = v12.parent_id
WHERE v1.ORG_ID = '6000001' UNION ALL SELECT 13 AS lv,
v13.org_code || '-' || v13.org_name AS codename,
v13.ORG_ID,
v13.parent_id,
v13.org_order,
v13.org_code,
v13.org_level
FROM tgtgtgtg v1
JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
JOIN tgtgtgtg v12 ON v11.ORG_ID = v12.parent_id
JOIN tgtgtgtg v13 ON v12.ORG_ID = v13.parent_id
WHERE v1.ORG_ID = '6000001') x
WHERE org_level <= 3
ORDER BY CASE
WHEN ',' || NVL(NULL, 'fingard') || ',' LIKE '%,' || ORG_ID || ',%' THEN
CASE
WHEN LENGTH(NVL(org_order, '')) = '9' THEN
org_order || ''
ELSE '1' || org_code
END
WHEN LENGTH(NVL(org_order, '')) = '9' THEN
'99999999' || org_order || ''
ELSE '999999991' || org_code END ) a)
WHERE rownum <= 10)
WHERE rn >= 1;

现场同学差集比较,确认改写后的SQL是等价的,执行时间从2.6秒降低到1.5秒能跑出结果。
原来18行的SQL改成了250多行后才优化了1秒的执行时间,实在没其他办法了,希望OB产研后续能CBO算子继续优化下。
OceanBase 金融项目优化案例的更多相关文章
- 数据库优化案例——————某市中心医院HIS系统
记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...
- 使用Jquery+EasyUI 进行框架项目开发案例解说之二---用户管理源代码分享
使用Jquery+EasyUI 进行框架项目开发案例解说之二 用户管理源代码分享 在上一篇文章<使用Jquery+EasyUI进行框架项目开发案例解说之中的一个---员工管理源代码分享> ...
- 深入浅出聊Unity3D项目优化:从Draw Calls到GC
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- Unity3D项目优化(转)
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- 联想ERP项目实施案例分析(10):回到最初再反思IT价值
联想ERP项目实施案例分析(10):回到最初再反思IT价值 投入上千万(未来每年的维护费也非常高),投入一年实施时间,高级副总裁亲自挂帅,各级业务部门管理者亲自负责.骨干业务人员充当区域IT实施者/推 ...
- Linux企业生产环境用户权限集中管理项目方案案例
企业生产环境用户权限集中管理项目方案案例: 1 问题现状 当前我们公司里服务器上百台,各个服务器上的管理人员很多(开发+运维+架构+DBA+产品+市场),在大家登录使用Linux服务器时,不同职能的员 ...
- 0515项目优化和List集合
0515项目优化和List集合 1. 项目优化 1.1 分析当前情况 问题 数据存储是数组形式,数据类型明确.复用度较低. 需求 Student操作使用的代码,StudentManager想要操作考虑 ...
- 【C#】项目优化实战
[C#]项目优化实战 一. 数据库设计 1. 常量的枚举值直接存中文不要存数字(注意是常量,如果显示值可变就不能) 例如:男女,在数据库中不要存1和0,直接存男和女. 这样的好处:读取数据的时候可以避 ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享
http://www.cnblogs.com/huyong/p/3454012.html 使用Jquery+EasyUI 进行框架项目开发案例讲解之五 模块(菜单)管理源码分享 在上四篇文章 ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之四 组织机构管理源码分享
http://www.cnblogs.com/huyong/p/3404647.html 在上三篇文章 <使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享> ...
随机推荐
- 慢sql治理经典案例分享
简介:菜鸟供应链金融慢sql治理已经有一段时间,自己负责的应用持续很长时间没有慢sql告警,现阶段在推进组内其他成员治理应用慢sql.这里把治理过程中的一些实践拿出来分享下. 作者 | 如期 来 ...
- AI和大数据结合,智能运维平台助力流利说提升核心竞争力
简介: 简介:本文整理自数智创新行--智能运维专场(上海站),流利说最佳实践演讲:<基于SLS千万级在线教育平台统一监控运营实践> 作者:孙文杰 流利说运维总监元乙 阿里云智能技术专家 优 ...
- WPF 已知问题 InputEventArgs 的 Timestamp 属性是静态的导致事件之间相互影响
本文记录一个 WPF 已知的设计问题,当前此问题已经被大佬修复,这个设计问题刚好属于比较边缘的模块,我写了这么多年的代码还没有踩到这个坑一次,也没有听到有谁提到这个坑 远古时候,不知道大佬是故意还是失 ...
- 技术书籍 — EffectiveMordenCpp 研读
一.类型推导 PROs: 源码某处的类型修改,可以自动传播其他地方 Cons: 会让代码更复杂(How?) 在模板类型推导时,有引用的实参会被视为无引用,他们的引用会被忽略 template<t ...
- threejs
- MSP 通过 Splashtop SOS 远程支持非托管设备
RMM 是 MSP 的绝佳工具.它们使 MSP 可以通过集中控制台来管理其所有客户计算机,通常使他们能够远程访问任何计算机以提供远程支持. 但是,这样做的一个很大限制是--并非所有客户设备都在 MSP ...
- pageOffice插件 springboot实现服务器上Word文档在线打开编辑保存
需求: 在oa系统上,想实现在线,服务器上doc,docx文档,在web打开,编辑.编辑后,可以再同步保存到服务器端. 开发环境: java springboot,thymeleaf 服务器环境: 无 ...
- 文件系统(四):FAT32文件系统实现原理
FAT32是从FAT12.FAT16发展而来,目前主要应用在移动存储设备中,比如SD卡.TF卡.隐藏的FAT文件系统现在也有被大量使用在UEFI启动分区中. 为使文章简单易读,下面内容特意隐藏了很多实 ...
- Must use PackageReference 解决办法
Must use PackageReference 这是因为 .net framework的项目 在nuget时,引用到了 .net core 下的包. 解决办法,把之前引用的相关包全部在nuget上 ...
- 【U8】快速获取u8单据的类型key值
win10下 打开 写字板,直接搜索栏搜索写字板打开. 登录u8,找到需要的单据,以基础档案存货为例,打开存货档案界面. 按住键盘ctrl+shift,鼠标左键单据单据上的某个按钮,以新增按钮为例,单 ...