中兴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 , ...
随机推荐
- 2023-7-27WPF的ContextMenu的传参绑定方式
WPF的ContextMenu的绑定方式 [作者]长生 ContextMenu为何不能正常绑定 在wpf中ContextMenu和ToolTip一样都是弹出层,与VisualTree已经分离了,只不过 ...
- 学习OI两年我到底收获了什么
做一个小小的总结 学习了两年的代码,刚刚要进入高中,留下一点文字给以前的学习做一个总结. 命中注定の邂逅-- 这两年之间,和编程产生了比学习更为低调的羁绊关系(我觉得用这个词语比较合适).编程给我带来 ...
- loader的三种配置方式
在这篇 webpack处理css资源 文章中使用几个常用的loader 来编译 css 代码. 但其实 loader 的配置方式不止一种,一起来看看其它方式~ 在 webpack.config.js ...
- [linux]常见内核TCP参数描述与配置
前言 所有的TCP/IP参数都位于/proc/sys/net目录下(请注意,对/proc/sys/net目录下内容的修改都是临时的,任何修改在系统重启后都会丢失),如果需要固化设置,则需要修改/etc ...
- RocketMQ Linux单机测试:简易快速部署指南及Dashboard控制台部署
目录 简介 开始 下载 增加环境变量 修改启动文件jvm大小 修改rocketmq配置文件 启动 快速测试 关闭 Dashboard 下载Dashboard 已编译jar包网盘下载 启动命令 可能遇到 ...
- 2023CISCN华中赛区re
2023CISCN华中赛区re 当时出的题 misc3-babyandroid 找so文件,加密过程也不复杂 每三个一组进行加密 这里就是先每个减去65 然后 大概是 y1=(31x1)%26+65 ...
- 开源Word文字替换小工具更新 增加文档页眉和页脚替换功能
ITGeeker技术奇客发布的开源Word文字替换小工具更新到v1.0.1.0版本啦,现已支持Office Word文档页眉和页脚的替换. 同时ITGeeker技术奇客修复了v1.0.0.0版本因替换 ...
- 【NestJS系列】核心概念:Middleware中间件
前言 用过express与koa的同学,对中间件这个概念应该非常熟悉了,中间件可以拿到Request.Response对象和next函数. 一般来讲中间件有以下作用: 执行任何代码 对请求与响应拦截并 ...
- 【译】.NET 8 拦截器(interceptor)
通常情况下,出于多种原因,我不会说我喜欢写关于预览功能的文章.我的大多数帖子旨在帮助人们解决他们可能遇到的问题,而不是找个肥皂盒或打广告.但是我认为我应该介绍这个 .NET 预览特性,因为它是我在 . ...
- Java爬虫实战系列2——动手写爬虫初体验
在上面的章节中,我们介绍了几个目前比较活跃的Java爬虫框架.在今天的章节中,我们会参考开源爬虫框架,开发我们自己的Java爬虫软件. 首先,我们下载本章节要使用到的源代码,本章节主要提供了基于HTT ...