Mysql改写子查询SQL优化案例
sql逻辑需求:需要定期统计表单数据,然后把汇总的结果展示在前端界面
根据业务逻辑实现了sql编写,产生了慢SQL
SELECT DISTINCT DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') as signDate,
count(sr.PRODUCT_NO) as totalSign,
(SELECT count(1)
FROM t_red_data t1
WHERE DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') =
DATE_FORMAT(t1.SIGN_DATE, '%Y-%m-%d')
AND t1.SIGN_TYPE = '1') AS sign,
(SELECT count(1)
FROM t_red_data t2
WHERE DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') =
DATE_FORMAT(t2.SIGN_DATE, '%Y-%m-%d')
AND t2.SIGN_TYPE = '2') AS supplySign
FROM t_red_data sr
WHERE sr.SIGN_DATE BETWEEN '2020-12-20 00:00:00' AND '2021-01-06 23:59:59'
GROUP BY DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') LIMIT 0, 10;
--耗费时间
10 rows in set (15.32 sec)
上面这条sql 的执行时间用了15.32秒,下面来看看慢在哪儿?
执行计划:
这sql执行计划挺差的,虽然where条件列上有索引IDX_SIGN_DATE,但数据库CBO并没有选择,走了全表扫描,因为时间范围选的太大,CBO估算后发现走完索引再回表查数据,代价太高。
下面让该sql强制走索引IDX_SIGN_DATE 看看效果:
SELECT DISTINCT DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') as signDate,
count(sr.PRODUCT_NO) as totalSign,
(SELECT count(1)
FROM t_red_data t1
WHERE DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') =
DATE_FORMAT(t1.SIGN_DATE, '%Y-%m-%d')
AND t1.SIGN_TYPE = '1') AS sign,
(SELECT count(1)
FROM t_red_data t2
WHERE DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') =
DATE_FORMAT(t2.SIGN_DATE, '%Y-%m-%d')
AND t2.SIGN_TYPE = '2') AS supplySign
FROM t_red_data sr force index (IDX_SIGN_DATE)
WHERE sr.SIGN_DATE BETWEEN '2020-12-20 00:00:00' AND '2021-01-06 23:59:59'
GROUP BY DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') LIMIT 0, 10;
--耗时时间更长了
10 rows in set (15.94 sec)
强制索引后执行计划:
执行慢的原因总结:CBO选择的执行计划是对的,因为走索引后代价更高,sql更慢。耗时主要是出现在DEPENDENT SUBQUERY上,根据where条件相当于把该表执行了三遍。主要解决子查询的问题。
通过表自关联消除列上子查询
SELECT signDate, totalSign, sign, totalSign - sign AS supplySign
FROM (SELECT DISTINCT DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') AS signDate,
count(sr.PRODUCT_NO) AS totalSign,
count(t1.ID) AS sign
FROM t_red_data sr
LEFT JOIN t_red_data t1
ON sr.id = t1.id
AND t1.SIGN_TYPE = '1'
WHERE sr.SIGN_DATE BETWEEN '2020-12-20 00:00:00' AND
'2021-01-06 23:59:59'
GROUP BY DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') LIMIT 0, 10) t;
--耗时时间
10 rows in set (1.75 sec)
改为自关联查询后就快了很多,接下来看下执行计划:
从执行计划可以看出,sr表作为驱动表,根据where条件筛选数据后拿到id再去驱动t1表,按条件匹配到10条数据后就结束,效率看起来不错...
但是还没结束,仅仅是统计下不同条件上的数据量,真的有必要自关联查询么?
自关联改写为case when
SELECT DISTINCT DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') as signDate,
count(sr.PRODUCT_NO) as totalSign,
count(case when sr.SIGN_TYPE = '1' then '1' else null end ) AS sign,
count(case when sr.SIGN_TYPE = '2' then '2' else null end ) AS supplySign
FROM t_red_data sr
WHERE sr.SIGN_DATE BETWEEN '2020-12-20 00:00:00' AND '2021-01-06 23:59:59'
GROUP BY DATE_FORMAT(sr.SIGN_DATE, '%Y-%m-%d') LIMIT 0, 10;
--执行耗时
10 rows in set (0.75 sec)
执行效率又进一步提升了,再次开口执行计划发生了啥改变:
该sql也变得更简单了,做了按where条件过滤数据后再把group by的排序下,相对之前的sql少做了不少事情,效率自然就高。另外,已经有了group by字句,本身已经消除了重复数据,所以前面的distinct关键词可以去掉了。
使用redis缓存查询结果
上面的sql 执行时间0.75秒还是不满足。 和业务沟通确认,这张表上1天前的数据不会改动,也就是根据时间条件多次执行这条sql结果不会发生变化。
把当天第一次查询出来的结果集缓存到redis,当sql查询日期条件改变时把缓存失效掉。这样就可以查询一次多次使用,访问redis效率更高,毫秒级返回。
Mysql改写子查询SQL优化案例相关推荐
- 性能为王:SQL标量子查询的优化案例分析
本篇整理内容是黄廷忠在"云和恩墨大讲堂"微信分享中的讲解案例,SQL优化及SQL审核,是从源头解决性能问题的根本手段,无论是开发人员还是DBA,都应当持续深入的学习SQL开发技能, ...
- mysql多表查询sql优化_SQL多表查询优化
SQL优化 1.执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就 ...
- 浅谈 MySQL 子查询及其优化
2019独角兽企业重金招聘Python工程师标准>>> 使用过oracle或者其他关系数据库的DBA或者开发人员都有这样的经验,在子查询上都认为数据库已经做过优化,能够很好的选择驱动 ...
- mysql in 子查询优化_mysql in 子查询 容易优化
mysql in 子查询 简单优化 大数量下,不要使用 in 嵌套子查询,性能很差,很容易卡死. ? 简单调整方式如下: select uid,nick_name from uc_users wher ...
- 浅谈mysql的子查询
2019独角兽企业重金招聘Python工程师标准>>> mysql的子查询的优化一直不是很友好,一直有受业界批评比较多,也是我在sql优化中遇到过最多的问题之一,mysql在处理子查 ...
- MySQL子查询的优缺点_浅谈mysql的子查询
浅谈mysql的子查询 mysql的子查询的优化一直不是很友好,一直有受业界批评比较多,也是我在sql优化中遇到过最多的问题之一,你可以点击这里 ,这里来获得一些信息,mysql在处理子查询的时候,会 ...
- 数据库周刊54丨2020 年度报告:PingCAP、腾讯云数据库、人大金仓、GoldenDB ;CPU 100% SQL优化案例;Mysql内存溢出处理;避免删库跑路黑天鹅……
热门资讯 [1.PingCAP 2020 年度报告|相信开放的力量 [摘要]本文为PingCAP 2020年度报告.盘点了PingCAP里程碑大事件:完成D轮2.7亿美元融资,创造全球数据库历史新的里 ...
- 19_clickhouse,数据查询与写入优化,分布式子查询优化,外部聚合/排序优化,基于JOIN引擎的优化,SQL优化案例,物化视图提速,查询优化常用经验法则,选择和主键不一样的排序键,数据入库优化
25.数据查询与写入优化 25.1.分布式子查询优化 25.1.1.分布式表的IN查询示例1(普通IN子查询.IN子查询为本地表) 25.1.2.分布式表的IN查询示例2(普通IN子查询.IN子查询为 ...
- mysql数据库子查询的使用_MySQL数据库使用子查询方式更新数据优化及思考
[环境介绍] 云数据库MySQL 5.7 [背景描述] 业务需要:需要对16370077的表数据进行更新部分数据操作 UPDATE P_MOXXXX_REXXXX SET FISAVAILABLE = ...
最新文章
- Spark Streaming 编程新手入门指南
- smarty模板引擎_7-自定义函数
- 【Linux系统编程】可重入和不可重入函数
- 行为设计模式:中介者
- Android: 解决动画完成后位置恢复到初始位置的问题
- 【贪心】【高精度】zoj3987 Numbers
- Python学习之快速入门
- IDEA项目搭建六——使用Eureka和Ribbon进行项目服务化
- cx_Oracle.DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loaded 解决方法
- Java CSV操作(导出和导入)
- ping 查看IP——MAC——计算机名
- 空域、频域、时域的解释
- freeswitch借助fail2ban屏蔽骚扰注册
- 关于springboot的配置注册循序问题
- 19、论文解读:Intensity Scan Context: Coding Intensity and Geometry Relations for Loop Closure Detection
- TDM阅读笔记,在推荐系统的应用
- shiro权限鉴定框架
- Java自幂数计算及其算法改进
- 论文解析[10] Contextual Transformer Networks for Visual Recognition
- 什么是护网(HVV)?需要什么技能?
热门文章
- 【报告分享】2021企业营销数字化转型研究报告.pdf(附下载链接)
- Python实战从入门到精通第十三讲——返回多个值的函数
- 【论文】Awesome Relation Extraction Paper(关系抽取)(PART V)
- 电商独立站-谷歌SEO指标
- perl模块net mysql_Perl模块实例化DBI Forks“Mysql服务器已经消失”
- 2019年的流水账和总结
- IntelliJ IDEA 创建Java Web项目
- 不得不会的10点Java基础知识
- python没有return语句的函数将返回_为什么Python没有return返回值
- mysql数据索引失效_MySQL索引失效的几种情况