MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。

读书笔记:一个人能走到自信、热情这一步是非常不容易的。自信可以滋养自体;而热情可以滋养他人。全能感有四个基本变化:全能自恋、全能暴怒、彻底无助、被害妄想。当我们降服全能自恋,从孤独的想象世界进入关系的现实世界,你会发现这个世界充满爱、热情、和创造力。你会爱上这个世界,也会爱上自己。


一、前言背景

二、如何判断 OR 找到慢查询SQL

2.1 开启慢查询日志

2.2 多慢的SQL,算是慢SQL?

2.3 慢查询日志分析

2.4 透过执行计划判断慢SQL

三、如何看懂执行计划

3.1  id-执行优先级顺序

3.2 select_type-查询类型

3.3 type-执行计划关键指标-有没有走索引?

3.3.1 const的意义-命中主键或者唯一索引

3.3.2 eq_ref-命中主键或者唯一索引

3.3.3 ref-命中了非唯一性索引

3.3.4 index-查询结果列全是索引

3.3.5 range-范围查询

3.3.6 all-全表扫描

四、SQL如何优化


一、前言背景

    今天是大年初八,祝大家新年快乐,开工大吉!

    刚从HR部门转过来做研发没多少年的小美,今天她气鼓鼓的和你说,运维那边说她的这个sql,过年期间被监控发现,执行很慢。让你帮她看看,她的SQL怎么慢了?要怎么优化?

    人美心善的小美,心里一定很委屈。这时候你要不要帮帮她?

......

    在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。

    掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。

    此时,可以教小美怎么判断和找到慢SQL,以及详细教她看sql的执行计划,并耐心给她讲一些生产实战的SQL优化经验。

二、如何判断 OR 找到慢查询SQL

    MySQL支持记录慢查询SQL日志,不过默认是关闭的。可以通过命令查看以及开启:

show variables like '%slow_query_log%';

2.1 开启慢查询日志

    通过在客户端会话,采用set global  进行全局设置MySQL慢SQL查询记录。比如:

set global slow_query_log='on';

    然后再次查询,慢SQL记录已经打开。

2.2 多慢的SQL,算是慢SQL?

    MySQL默认执行时间大于10s,就是慢SQL。可以通过查看参数long_query_time,比如:

show variables like '%long_query_time%';

    在日常工作中,慢SQL就意味着客户体验差。对于系统来说,一条普通业务SQL查询,原则上最慢不得大于1s。而涉及对客展业的后台SQL,响应时间绝对不允许大于3s。对于高级别的系统,秒级响应的SQL实际就是慢SQL,需要进行SQL优化、技术架构优化。

2.3 慢查询日志分析

    慢SQL日志内容长什么样?

    为了方便验证,我们把参数long_query_time设置为0s。

    不过这里需要注意,在客户端会话中set GLOBAL long_query_time之后,需要关闭该会话客户端,重新打开才能看到long_query_time新值。以及需要在新会话窗口执行sql,才会被当做慢SQL记录到log日志。

修改为0,并重新打开新会话执行查询SQL,这样所有sql都被MySQL当中慢sql记录到我们的日志里:

/usr/local/var/mysql/ladingjieniu-slow.log。

在slow log里,我们可以看到慢查询sql内容,以及查询时间、查询的用户名、扫描数据行数、最后获得结果数据等信息。

2.4 透过执行计划判断慢SQL

    在未发版上线前,测试环境由于数据量有限,无法及时监控发现慢SQL。此时针对高等级核心业务场景接口SQL,可以通过explain 查看SQL执行计划的type字段来评估SQL性能。

    type值常见的有const、ref、eq_ref、all、range这些。一个查询sql的执行计划type要求至少是index才是优秀,如果是all就要考虑纳入优化。

    接下来,我们具体分析执行计划应该如何看。

三、如何看懂执行计划

    我们拿一个执行计划出来看一下。比如:

里面有id、select_type、table、type、key、ref等字段。每个都有它特定意义。

3.1 id-执行优先级顺序

    在SQL架构原理那一篇文章,我们说过,sql最终如何执行是由核心组件查询优化器决定。查询优化器通过询问存储引擎、sql索引情况来生成SQL执行树。一个复杂的SQL,里面有很多联合查询、子查询。具体哪个先执行,这里就可以通过id来看到查询优化器指定的顺序。

    比如上图,id值有【1、1、1、2】。这个执行顺序是2,然后是1。三个1从上往下执行。

    原则是:id值越大,优先级越高。会被优先执行。如果id值相等,在执行计划前面的先执行。

3.2 select_type-查询类型

    查询类型,常见的有simple、primary、subquery、derived、union、union all这些。看名字顾名思义,有简单查询、主查询、子查询、联合查询。具体展开:

simple:表示单表查询或者简单查询。比如:

primary:表示主查询。

     执行计划select type是primary,往往都是SQL是复杂查询,里面有子查询。primary和subquery或者derived一起出现。比如如下:

union: sql里有union,union关键字后的select 语句就被标注select type为【union】。

derived和subquery的区别,这里也说一下。

select列表,where 条件里的子查询是subquery。而如果子查询是在from结果集,select type就是derived。

比如:

explain select p.*,(select role_id from sys_user_role) as role_id from (select user_id from sys_user) t,sys_user_post p;

from后面的这个t结果集子查询就是derived类型,而select里的子查询【(select role_id from sys_user_role)】就是subquery类型。

3.3 type-执行计划关键指标-有没有走索引?

    常见的有const、all、range、index、ref、eq_ref这些。这里查询表现最好的按高到底排序:

const> eq_ref> ref > range > index > all。

3.3.1 const的意义-命中主键或者唯一索引

    当我们执行计划type为const,说明命中了主键索引或者唯一索引。比如如下sql:

explain select * from sys_user where user_id=1;

where条件是唯一索引user_id:

3.3.2 eq_ref-命中主键或者唯一索引

    当type为eq_ref时,说明也是命中了索引,而且和const类型,也是命中的主键或者唯一索引。sql里where条件,用到了主键索引进行多个等值匹配。

    比如如下sql的查询计划type出现了 eq_ref类型:

explain select * from sys_user where user_id in (select user_id from sys_user_role);

3.3.3 ref-命中了非唯一性索引

    而ref也是命中索引,但是和eq_ref不同的是,ref是命中了非唯一性索引。比如:

user_mvcc_demo表name是非唯一索引,执行sql:

explain select * from user_mvcc_demo where name='拉丁哥8';

    查询计划type就是ref。

3.3.4 index-查询结果列全是索引

    比如我们这个sys_user_role表,里面两个字段都是索引。查询计划,虽然是全部查询,但是tye就是index。

3.3.5 range-范围查询

    查询条件里使用了大于小于,between之类的查询。

3.3.6 all-全表扫描

    如果sql查询里,type有all,那就是触发了全表扫描,没有走索引。需要重点关注,尝试看能否优化。

    其他的顺便说一下,possible_keys就是可能用到的索引、key表示实际用的索引。

ref就是哪些列被用来关联索引查询。

rows,表示预计要读取多少行数据。

四、SQL如何优化

    其实SQL优化的前期慢sql定位、以及执行计划的分析,我们已经大概确定sql慢在哪里,尤其是复杂的sql。通过执行计划,可以清晰看到sql是怎么执行的,以及是否走索引,不管是select字段,from子集、中间结果表、where条件、还是排序order by,或者group by,还是having,每一部分都需要关注优化。

    而sql优化的核心,重点是让sql尽可能的走索引+合理创建索引。通过执行计划,我们可以很快发现,未及时创建的索引。而sql如何写,才会触发走索引呢?这里有几个原则:

1、最左匹配原则。

2、sql里尽量不要做类型转换、函数计算。

3、like、范围查询要谨慎。

4、尽量不要出现*。

    这几个原则非常朴实,有的大佬甚至整理了顺口溜方便大家做SQL优化。然而随着nosql、内存数据库的广泛应用,小公司数据量小sql优化需求不多;而大企业,有足够成熟的技术架构,用到sql优化的很多时候就是做大数据数仓的火伴,写sql就是写代码的数仓同学,需要对sql有深入理解。其他研发真正用到sql优化的,刚好就是中小企业研发同事,系统有一定的数据量,但是在基础设施投入有限,人力有限,就需要大家投入研发精力去进行SQL优化。

    sql优化之外,能继续深入优化的方法还有数据预处理计算、以及联合索引、应用缓存的合理搭配应用。

    最后,SQL优化就一句话:合理创建索引,且让SQL查询应用上索引。


推荐阅读拉丁解牛相关专题系列(欢迎交流讨论):

1、JVM进阶调优系列(3)堆内存的对象什么时候被回收?

2、JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

3、JVM进阶调优系列(1)类加载器原理一文讲透

4、JAVA并发编程系列(13)Future、FutureTask异步小王子

5、MySQL进阶突击系列(05)突击MVCC核心原理 | 左右护法ReadView视图和undoLog版本链强强联合

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
关系型数据库 MySQL Linux
MySQL原理简介—6.简单的生产优化案例
本文介绍了数据库和存储系统的几个主题: 1. **MySQL日志的顺序写和数据文件的随机读指标**:解释了磁盘随机读和顺序写的原理及对数据库性能的影响。 2. **Linux存储系统软件层原理及IO调度优化原理**:解析了Linux存储系统的分层架构,包括VFS、Page Cache、IO调度等,并推荐使用deadline算法优化IO调度。 3. **数据库服务器使用的RAID存储架构**:介绍了RAID技术的基本概念及其如何通过多磁盘阵列提高存储容量和数据冗余性。 4. **数据库Too many connections故障定位**:分析了MySQL连接数限制问题的原因及解决方法。
|
1天前
|
关系型数据库 MySQL 数据库
从MySQL优化到脑力健康:技术人与效率的双重提升
聊到效率这个事,大家应该都挺有感触的吧。 不管是技术优化还是个人状态调整,怎么能更快、更省力地完成事情,都是我们每天要琢磨的事。
49 23
|
1天前
|
SQL 关系型数据库 MySQL
MySQL原理简介—11.优化案例介绍
本文介绍了四个SQL性能优化案例,涵盖不同场景下的问题分析与解决方案: 1. 禁止或改写SQL避免自动半连接优化。 2. 指定索引避免按聚簇索引全表扫描大表。 3. 按聚簇索引扫描小表减少回表次数。 4. 避免产生长事务长时间执行。
|
1天前
|
SQL 存储 关系型数据库
MySQL原理简介—10.SQL语句和执行计划
本文介绍了MySQL执行计划的相关概念及其优化方法。首先解释了什么是执行计划,它是SQL语句在查询时如何检索、筛选和排序数据的过程。接着详细描述了执行计划中常见的访问类型,如const、ref、range、index和all等,并分析了它们的性能特点。文中还探讨了多表关联查询的原理及优化策略,包括驱动表和被驱动表的选择。此外,文章讨论了全表扫描和索引的成本计算方法,以及MySQL如何通过成本估算选择最优执行计划。最后,介绍了explain命令的各个参数含义,帮助理解查询优化器的工作机制。通过这些内容,读者可以更好地理解和优化SQL查询性能。
|
18天前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
5天前
|
关系型数据库 MySQL 数据库
Docker Compose V2 安装常用数据库MySQL+Mongo
以上内容涵盖了使用 Docker Compose 安装和管理 MySQL 和 MongoDB 的详细步骤,希望对您有所帮助。
72 42
|
23天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
169 0
|
2月前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
69 3
|
2月前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
109 3
|
2月前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
108 2

相关产品

  • 云数据库 RDS MySQL 版