陆老师好久没找我,今天他在营运商遇到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 才能出结果。

 SQL索引优化:

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)的更多相关文章

  1. mysql的sql优化案例

    前言 mysql的sql优化器比较弱,选择执行计划貌似很随机. 案例 一.表结构说明mysql> show create table table_order\G***************** ...

  2. SQL优化案例—— RowNumber分页

    将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...

  3. SQL 优化案例 1

    create or replace procedure SP_GET_NEWEST_CAPTCHA( v_ACCOUNT_ID in VARCHAR2, --接收短信的手机号 v_Tail_num i ...

  4. SQL 优化案例

    create or replace procedure SP_GET_NEWEST_CAPTCHA( v_ACCOUNT_ID in VARCHAR2, --接收短信的手机号 v_Tail_num i ...

  5. SQL优化的一些总结 SQL编写一般要求

    SQL编写一般要求---SQL语句尽可能简单---分解联接保证高并发---同数据类型的列值比较---不在索引列做运算---禁止使用SELECT *---避免负向查询和%前缀模糊查询---保持事务(连接 ...

  6. 智能SQL优化工具--SQL Optimizer for SQL Server(帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 )

    SQL Optimizer for SQL Server 帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 SQL Optimizer for SQL Server 让 SQL Serve ...

  7. Oracle之SQL优化专题01-查看SQL执行计划的方法

    在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...

  8. Oracle之SQL优化专题02-稳固SQL执行计划的方法

    首先构建一个简单的测试用例来实际演示: create table emp as select * from scott.emp; create table dept as select * from ...

  9. 数栈SQL优化案例:隐式转换

    MySQL是当下最流行的关系型数据库之一,互联网高速发展的今天,MySQL数据库在电商.金融等诸多行业的生产系统中被广泛使用. 在实际的开发运维过程中,想必大家也常常会碰到慢SQL的困扰.一条性能不好 ...

  10. Mysql大范围分页优化案例

    在BBS线上业务抓到如下分页SQL: meizu_bbs meizu_bbs Query Sending data , meizu_bbs meizu_bbs Query Sending data , ...

随机推荐

  1. TypeScript:接口

    介绍 TypeScript的核心原则之一是对值所有的结构类型进行类型检查.在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义约束. 接口的基本使用 interface ...

  2. Django: 获取头信息

    如何获取请求头信息 使用如下函数request.META.get("HTTP_请求头函数"),需要注意的是,请求头变量需要全部大写. 其他注意事项如下所示: 如果headerkey ...

  3. C#.NET 国密SM3 HASH 哈希 与JAVA互通 ver:20230803

    C#.NET 国密SM3 HASH 哈希 与JAVA互通 ver:20230803 .NET 环境:.NET6 控制台程序(.net core). JAVA 环境:JAVA8,带maven 的JAVA ...

  4. 《HelloGitHub》第 89 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

  5. 《Kali渗透基础》15. WEB 渗透

    @ 目录 1:WEB 技术 1.1:WEB 攻击面 1.2:HTTP 协议基础 1.3:AJAX 1.4:WEB Service 2:扫描工具 2.1:HTTrack 2.2:Nikto 2.3:Sk ...

  6. 《SQL与数据库基础》17. InnoDB引擎

    目录 InnoDB引擎 逻辑存储结构 架构 内存结构 磁盘结构 后台线程 事务原理 事务基础 redo log undo log MVCC 基本概念 隐式字段 undo log版本链 readView ...

  7. Java爬虫实战系列——常用的Java网络爬虫库

    常用的Java网络爬虫库 Java 开发语言是业界使用最广泛的开发语言之一,在互联网从业者中具有广泛的使用者,Java 网络爬虫可以帮助 Java 开发人员以快速.简单但广泛的方式为各种目的抓取数据. ...

  8. CodeForces 1367E Necklace Assembly

    题意 给定一个字符串\(s\),长度为\(n\),一根项链为一个环,定义一根项链为\(k-beautiful\),则该项链顺时针转\(k\)下后与原项链相等,给出\(k\),请构造一根最长的\(k-b ...

  9. 领域驱动模型DDD(四)——Eventuate Tram Saga源码讲解

    前言 虽然本人一直抱怨<微服务架构设计模式>中DDD模式下采用的Eventuate Tram Saga不算简单易用,但是为了更加深入了解原文作者的设计思路,还是花了点时间去阅读源码,并且为 ...

  10. SpringBoot打成jar运行后无法读取resources里的文件

    开发一个word替换功能时,因替换其中的内容功能需要 word 模版,就把 word_replace_tpl.docx 模版文件放到 resources 下 在开发环境中通过下面方法能读取word_r ...