MySQL exists关联子查询SQL性能及其低下优化之等值子查询转换

    2018年4月20日,移动某平台江苏某业务系统发起SQL调优请求,在本次MySQL调试过程中遇到了exists关联子查询导致的sql
性能及其低下,并且相关的SQL语句执行速度及其不稳定忽快忽慢;通过重写相关SQL的exists部分修改成等值子查询,相关sql的
性能得到极大提高,并且执行速度比较稳定。本次SQL优化过程记录如下:
    1、环境信息:
    操作系统版本:CENTOS 7.2.1151
    数据库版本:5.7.17-log
    2、查看MySQL慢日志相关信息
ysql>show variables like '%slow_query_%';
-+-------------------------------------------+--------------------------------------------------------------------------------+
|        Variable_name                        |                                    Value                                      |
-+-------------------------------------------+--------------------------------------------------------------------------------+
|slow_query_log                               | ON                                                                            |
|slow_query_log_file                         |/data/mysql/db/elog/slow.log                                                    |
-+-------------------------------------------+--------------------------------------------------------------------------------+
    2、使用pt工具分析MySQL的慢日志
cd   /data/mysql/db/elog
pt-query-digest slow.log  --since '2018-04-13 00:00:00'  --until '2018-04-19 00:00:00' >>slow_report_log
    3、查看慢日志分析报告 slow_report_log

通过慢日志分析报告发现两条运行缓慢的SQL语句Query_ID分别是0xEA33702BDD78E0BA、0x56B6B418ADAAB135,其中
0xEA33702BDD78E0BA的响应时间占据了整个数据库时间的97.1%,是重点优化对象。
    4、明确需要优化的对象
--第一条需要优化的重点对象 0xEA33702BDD78E0BA

--SQL执行计划

-- SQL执行统计信息概要

--第二条要优化的SQL对象
0x56B6B418ADAAB135

--SQL执行计划

-- SQL执行统计信息概要

    5、首先看第一条SQL语句,自己的优化思路,确定SQL语句中慢的具体位置
--对第一条SQL语句拆分,以union为界分两部分
-- 0xEA33702BDD78E0BA第一部分:0xEA33702BDD78E0BA_part1

0xEA33702BDD78E0BA_part1部分SQL语句查询只有13条记录,执行速度非常快0.00秒完成

-- 0xEA33702BDD78E0BA第二部分:0xEA33702BDD78E0BA_part2

0xEA33702BDD78E0BA_part2部分SQL(该部分查询正常出结果是103条数据)语句执行超过10s,超时退出

    6、接下来着重关注 0xEA33702BDD78E0BA第二部分:0xEA33702BDD78E0BA_part2

观察SQL语句发现有EXISTS关联子查询,我的理解是,原先sql被优化器改写,主查询执行多次,每次主查询sql都不同,
都会发起物理读盘扫表。于是考虑将其改为等值连接子查询:

-- SQL改写后(查询结果集与修改前一致): 两个等值查询表结果集在内存,接下来是最终 结果集匹配和过滤,执行速度只有0.01秒

7、修改后的完整SQL如下

--修改后的sql执行速度,有原先的超过10s超时中断退出降低到0.00秒以下。

--SQL改写后的执行计划


8、第二条SQL语句采用第一条SQL语句优化方法,将exists关联子查询改写为表关联的等值子查询
--改写前的执行效率

--改写后的执行效率

--改写后的SQL执行计划


9、总结
通过观察SQL改写前后的执行计划,可以发现改写后的SQL 执行中间结果集均已缓存到内存(Using join buffer(Block Nested Loop)),内存结果集匹配过滤降低了表的物理IO,从而提高了SQL的执行性能。



猜你喜欢

转载自blog.csdn.net/www_xue_xi/article/details/80017288