中兴GoldenDB(MYSQL)营运商SQL优化案例(超复杂SQL)
陆老师好久没找我,今天他在营运商遇到2条性能慢的SQL,说找了好多专家老手看了都优化不了,然后就找到我打算给我玩玩。
第一次接触营运商行业的SQL,妈呦还真的复杂
SQL1:
SELECT WORK_ORDER_ID as workOrderId,
WORK_ITEM_ID as workItemId,
TRACE_ID as traceID,
TOTAL_DATE as totalDate,
SEND_TIME as sendTime,
SEND_STATUS as sendStatus,
REQUEST_TIME as requestTime,
REMARKS as remarks,
PROVINCE as province,
PRIORITY as priority,
nvl(PHONE_NO, '0') as phoneNo,
PARENTCALLID as parentcallid,
OTHER_CHAR2 as otherChar2,
OTHER_CHAR1 as otherChar1,
OTHER_CHAR as otherChar,
OSS_ORDER_ID as ossOrderId,
nvl(ORDER_TYPE, '0') as orderType,
ORDER_CREATE_TIME as orderCreateTime,
OP_TIME as opTime,
OP_CODE as opCode,
nvl(MOD_VALUE, '0') as modValue,
nvl(LOGIN_NO, '0') as loginNo,
IOM_RECEIVE_TIME as iomReceiveTime,
IOM_COMPLETE_TIME as iomCompleteTime,
nvl(IMSI_NO, '0') as imsiNo,
ID_NO as idNo,
HLR_CODE as hlrCode,
GROUP_ID as groupId,
CRM_ORDER_ID as crmOrderId,
COMMAND_ID as commandId,
COMMAND_COUNT as commandCount,
COMMAND_CODE as commandCode,
CMS_RECEIVE_TIME as cmsReceiveTime,
CMS_COMPLETE_TIME as cmsCompleteTime,
ACK_TIME as ackTime,
ACK_INFO as ackInfo,
ACK_CODE as ackCode
FROM px_lu
WHERE send_status = '0'
and mod(to_number(trim(phone_no)), 1) = 0
ORDER BY request_time, command_id limit 500;
执行时间:500 rows in set (0.853 sec)
这条分页SQL在 ORACLE 上 30ms 就可以跑出来,在 GoldenDB 要跑近 1s 才能出结果。
SQL1 索引优化:
create index idx_1_2_3 on px_lu (send_status,request_time, command_id );
500 rows in set (0.013 sec)
索引加上以后 0.013 s 就可以跑出结果,非常简单。
SQL2:
select new_busi_code,
new_status_cd,
table_name,
new_group_id,
count(1) count
from (select (select nvl((select x.rule_value
from vccccx t,
frtgh x
where t.rule_code = '1000000048'
and t.busi_rule_code = x.busi_rule_code
and t.busi_code = a.busi_code), decode(busi_level, '2', par_busi_code, BUSI_CODE))
from sffsss
where busi_code = a.busi_code) as new_busi_code,
(nvl((select x.rule_value
from vccccx t,
frtgh x
where t.rule_code = '1000000046'
and t.busi_rule_code = x.busi_rule_code
and t.busi_code = a.busi_code), 's')) new_status_cd,
(select op_note as table_name
from swbbbbbb
where maindata_code = 'RS-NO-0001'
and maindata_value = (nvl((select x.rule_value
from vccccx t,
frtgh x
where t.rule_code = '1000000046'
and t.busi_rule_code = x.busi_rule_code
and t.busi_code = a.busi_code), 's'))) table_name,
nvl((select parent_group_id
from dsdsd
where group_id = a.group_id
and parent_level = nvl((select x.rule_value
from vccccx t,
frtgh x
where t.rule_code = '1000000047'
and t.busi_rule_code = x.busi_rule_code
and t.busi_code = a.busi_code), 3)), a.group_id) as new_group_id
from dsdsd b,
rsrsrs a
WHERE b.group_id = a.group_id
AND a.status_cd in ('2', 'y')
AND b.parent_group_id = '14'
and a.region_code = '2201'
and a.tenant_id = '22'
and b.tenant_id = '22'
AND a.rec_Time <= to_date(TO_CHAR(SYSDATE, 'YYYYMMDD') || ' 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
where new_busi_code is not null
and new_status_cd is not null
and new_group_id is not null
group by new_busi_code, new_status_cd, table_name, new_group_id;
10 rows in set (9 min 46.240 sec)
这条SQL的表连接关系是真的超级复杂,来在ORACLE上跑30s可以出结果,在GoldenDB 却快跑10分钟才能出结果。
其实主要就是慢在标量子查询,只要改写成左连接性能就可以提升上来,里面的逻辑真的是太复杂了,我花了不少时间搞清关系,营运商SQL的复杂程度总算见到了。
SQL2等价改写:
select new_busi_code,
new_status_cd,
table_name,
new_group_id,
count(1) count
from (
SELECT COALESCE(rv1.rule_value, DECODE(cb.busi_level, '2', cb.par_busi_code, cb.BUSI_CODE)) AS new_busi_code,
COALESCE(rv2.rule_value, 's') AS new_status_cd,
mv.op_note AS table_name,
COALESCE(cgr.parent_group_id, a.group_id) AS new_group_id
FROM rsrsrs a
LEFT JOIN dsdsd b ON b.group_id = a.group_id
LEFT JOIN sffsss cb ON cb.busi_code = a.busi_code
LEFT JOIN vccccx br1 ON br1.busi_code = a.busi_code AND br1.rule_code = '1000000048'
LEFT JOIN frtgh rv1 ON br1.busi_rule_code = rv1.busi_rule_code
LEFT JOIN vccccx br2 ON br2.busi_code = a.busi_code AND br2.rule_code = '1000000046'
LEFT JOIN frtgh rv2 ON br2.busi_rule_code = rv2.busi_rule_code
LEFT JOIN swbbbbbb mv
ON mv.maindata_value = COALESCE(rv2.rule_value, 's') AND mv.maindata_code = 'RS-NO-0001'
LEFT JOIN vccccx br3 ON br3.busi_code = a.busi_code AND br3.rule_code = '1000000047'
LEFT JOIN frtgh rv3 ON br3.busi_rule_code = rv3.busi_rule_code
LEFT JOIN dsdsd cgr ON cgr.group_id = a.group_id AND cgr.parent_level = COALESCE(rv3.rule_value, 3)
WHERE a.status_cd IN ('2', 'y')
AND b.parent_group_id = '14'
AND a.region_code = '2201'
AND a.tenant_id = '22'
AND b.tenant_id = '22'
AND a.rec_Time <= to_date(TO_CHAR(SYSDATE, 'YYYYMMDD') || ' 00:00:00', 'yyyy-mm-dd hh24:mi:ss')
AND COALESCE(rv1.rule_value, DECODE(cb.busi_level, '2', cb.par_busi_code, cb.BUSI_CODE)) IS NOT NULL
AND COALESCE(rv2.rule_value, 's') IS NOT NULL
AND COALESCE(cgr.parent_group_id, a.group_id) IS NOT NULL
)
where new_busi_code is not null
and new_status_cd is not null
and new_group_id is not null
group by new_busi_code, new_status_cd, table_name, new_group_id;
10 rows in set (3 min 12.370 sec)
改写完以后运行速度从9分钟可以降到3分钟左右就能出结果,依然是很慢,还有继续优化空间。
SQL2创建索引继续优化:
create index idx_1_2_3 ON rsrsrs(group_id,busi_code, status_cd, region_code, tenant_id, rec_Time);
create index idx_4_5_6 ON dsdsd(group_id, parent_group_id, tenant_id);
create index idx_7_8_9 ON sffsss(busi_code);
create index idx_11_12_13 ON vccccx(busi_code, rule_code, busi_rule_code);
create index idx_14_15_16 ON frtgh(busi_rule_code);
create index idx_17_18_19 ON swbbbbbb(maindata_value, maindata_code);
10 rows in set (48.876 sec)
最终通过等价改写 + 索引优化手段,SQL2从9分钟左右的执行时间降到48秒就可以出结果,基本没有继续优化的空间了。
中兴GoldenDB(MYSQL)营运商SQL优化案例(超复杂SQL)的更多相关文章
- mysql的sql优化案例
前言 mysql的sql优化器比较弱,选择执行计划貌似很随机. 案例 一.表结构说明mysql> show create table table_order\G***************** ...
- SQL优化案例—— RowNumber分页
将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...
- SQL 优化案例 1
create or replace procedure SP_GET_NEWEST_CAPTCHA( v_ACCOUNT_ID in VARCHAR2, --接收短信的手机号 v_Tail_num i ...
- SQL 优化案例
create or replace procedure SP_GET_NEWEST_CAPTCHA( v_ACCOUNT_ID in VARCHAR2, --接收短信的手机号 v_Tail_num i ...
- SQL优化的一些总结 SQL编写一般要求
SQL编写一般要求---SQL语句尽可能简单---分解联接保证高并发---同数据类型的列值比较---不在索引列做运算---禁止使用SELECT *---避免负向查询和%前缀模糊查询---保持事务(连接 ...
- 智能SQL优化工具--SQL Optimizer for SQL Server(帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 )
SQL Optimizer for SQL Server 帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 SQL Optimizer for SQL Server 让 SQL Serve ...
- Oracle之SQL优化专题01-查看SQL执行计划的方法
在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...
- Oracle之SQL优化专题02-稳固SQL执行计划的方法
首先构建一个简单的测试用例来实际演示: create table emp as select * from scott.emp; create table dept as select * from ...
- 数栈SQL优化案例:隐式转换
MySQL是当下最流行的关系型数据库之一,互联网高速发展的今天,MySQL数据库在电商.金融等诸多行业的生产系统中被广泛使用. 在实际的开发运维过程中,想必大家也常常会碰到慢SQL的困扰.一条性能不好 ...
- Mysql大范围分页优化案例
在BBS线上业务抓到如下分页SQL: meizu_bbs meizu_bbs Query Sending data , meizu_bbs meizu_bbs Query Sending data , ...
随机推荐
- linux 内核的ksm机制
KSM(Kernel Samepage Merging),是Linux内核中的一种内存优化机制,它能够通过将多个应用程序中的相同内存页合并,实现虚拟内存的节约.KSM通过比较不同进程间的虚拟内存页,如 ...
- python: 判断是否是某一类型
函数isinstance 语法 isinstance(object, classinfo) 参数 object -- 实例对象. classinfo -- 可以是直接或间接类名.基本类型或者由它们组成 ...
- 笔记:KMP的复习
Record 一个重要的字符串算法,这是第三次复习. 通过总结我认为之所以某个算法总是忘记,是因为大脑始终没有认可这种算法的逻辑(也就是脑回路). 本篇主要讲解从KMP的应用场景,再到算法知识,以及例 ...
- Unity的IPreprocessShaders:深入解析与实用案例
Unity IPreprocessShaders Unity IPreprocessShaders是Unity引擎中的一个非常有用的功能,它可以让开发者在编译Shader时自定义哪些操作需要被执行.这 ...
- 探索ChatGPT的Fine-tuning和Embeddings
1.概述 今天我们将深入探索ChatGPT的两项核心技术:Fine-tuning(微调)和Embeddings(嵌入).这些技术在现代自然语言处理领域扮演着至关重要的角色,为模型的性能提升和适应特定任 ...
- 《Linux基础》04. 用户管理 · 用户组 · 相关文件 · 权限管理
@ 目录 1:用户管理指令 1.1:添加用户 1.2:修改用户密码 1.3:用户切换与注销 1.4:删除用户 1.5:查询用户信息 1.6:查看当前登录用户 1.7:查看有哪些用户 2:用户组指令 2 ...
- 【Python进阶-PyQt5】00PyQt5简介
0.图形用户界面-开发选择 在Python基础的教程中,我们程序的用户交互界面都是运行窗口.这个运行窗口对于我们编程者来说直观明了,但是对于一些相对复杂的程序,用户使用上就会变得十分麻烦.所以,我们要 ...
- C++算法之旅、04 基础篇 | 第一章
常用代码模板1--基础算法 - AcWing ios::sync_with_stdio(false) 提高 cin 读取速度,副作用是不能使用 scanf 数据输入规模大于一百万建议用scanf 快速 ...
- C++的编译链接与在vs中build提速
通过gcc或msvc,clang等编译器编译出来的C++源文件是.o文件.在windows上也就是PE文件,linux为ELF文件,在这一步中,调用其它代码文件中的函数的函数地址是未知的(00000) ...
- [编程基础] Python内置模块collections使用笔记
collections是Python标准库中的一个内置模块,它提供了一些额外的数据结构类型,用于增强Python基础类型如列表(list).元组(tuple)和字典(dict)等.以下是对collec ...