中兴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 , ...
随机推荐
- PerfView专题 (第十五篇): 如何洞察 C# 中的慢速方法
一:背景 1. 讲故事 在 dump 分析旅程中,经常会遇到很多朋友反馈一类问题,比如: 方法平时都执行的特别快,但有时候会特别慢,怎么排查? 我的方法第一次执行特别慢,能看到慢在哪里吗? 相信有朋友 ...
- 侯捷C++STL源码分析
STL六大部件 容器(Containers):放东西,需要占用内存. 分配器(Allocators):支持容器. 算法(Algorithms):操作容器里面的数据. 迭代器(Iterators):容器 ...
- Nginx:超时 keeplive_timeout 配置
参考:Nginx的超时keeplive_timeout配置详解 HTTP 是一种无状态协议,客户端向服务器发送一个 TCP 请求,服务端响应完毕后断开连接. 如果客户端向服务器发送多个请求,每个请求都 ...
- vulnhub_me and my grilfriend
解题步骤 主机nmap扫描,开放22和80端口 访问该ip,发现只能本地访问 查看源代码,提示需要使用x-forwarded-for的请求头,可以在burp suite中每次添加一个请求头,也可以使用 ...
- Cilium系列-11-启用带宽管理器
系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, ...
- npm install 下载依赖的过程
首先检查.npmrc文件,项目级.npmrc文件>用户级的.npmrc文件>全局性的.npmrc文件>npm内置的.npmrc文件 是否有lock文件 没有lock文件 从npm远程 ...
- CSS基础(4)
目录 1 定位 1.1 为什么需要定位 1.2 定位组成 1.2.1 边偏移(方位名词) 1.2.2 定位模式 (position) 1.3 定位模式介绍 1.3.1 静态定位(static) - 了 ...
- Facade Pattern and Encapsulation—— Structure Class
如果只看代码的话,应该可以说Facade pattern(门面设计模式)是一种最简单的代码结构,不就封装吗!这玩意谁不会! 还是看它背后所蕴含的思想吧,看了之后发现背后的思想也很简单,非常好理解. - ...
- nmcli 命令设置网络
nmcli 命令设置网络 设置静态 IP 地址 sudo nmcli connection modify "连接名称" ipv4.addresses IP地址/子网掩码 设置网关 ...
- 在 Android Studio Java 项目里混合 Kotlin 编程
首先,先搞明白一个概念,这里的 Java 混合 Kotlin 是指文件层级的混合,即 Java 代码还是写在 .java 文件中,Kotlin 代码还是写在 .kt 文件中,只不过是可以在 Java ...