MySQL慢查询怎么解决
背景:
对于SQL语句的慢查询问题,不论是实际项目还是面试都是可能会遇到的问题。而当提到如何解决慢查询时,绝大多数第一反应就是检查sql语句是否走索引、以及sql语句优化等等,那么是所有的情况都是sql语句的问题吗?那么本文将从流程的底层来介绍解决方案。
一、SQL语句执行流程
Server层:
- 首先需要与客户端建立连接,通过连接器进行管理连接,权限验证。
- 然后分析器进行词法分析和语法分析,将SQL拆分成不可再分的原子符号,最后转换成抽象语法树。
- 然后优化器会根据分析器的结果生成一个执行计划,以及选择哪个索引。
- 最后通过执行器调取存储引擎的API进行数据操作。
在存储引擎层,InnoDB会将数据读取到Buffer Pool(缓冲池)进行操作,然后根据索引找到对应的索引页,以及数据页。然后将得到的数据返回给客户端。
二、慢查询分析
1、explain分析sql语句
当SQL语句执行慢的时候,有可能是分析器选择了错误的索引,那么可以通过MySQL的explain语句,对sql语句进行分析,查看是否走了索引等信息,来应对。详细内容在 SQL优化与索引优化篇,此处不再做过多赘述。
💡2、连接数过小
在上述MySQL执行流程设计的底层中,客户端和MySQL的交互首先就是通过连接器来建立长连接。
客户端通过一条长连接发送SQL语句命令交由MySQL执行,执行完毕后将再将数据通过长连接返回给客户端,但是在此过程中一个长连接只能执行一个命令,后面的SQL语句需要等待前面的SQL语句执行完毕才能执行。
所以有些时候通过日志查看一条SQL语句执行了很久,但是单拎出来执行只需要很短的时间的时候,那么这时候可能就是连接数过少导致的。
所以就可以通过增加客户端应用侧和MySQL的连接数来解决。
MySQL连接数
MySQL的默认最大连接数是100,上限是16384,可以根据实际情况来调整参数,可以通过命令或者配置文件来修改该参数。
命令:
SET GLOBAL max_connections = 新的连接数;
通过配置:
为了永久性地设置最大连接数,你需要编辑MySQL的配置文件,通常位于以下路径之一:
对于Linux系统:/etc/mysql/my.cnf 或 /etc/my.cnf
对于Windows系统:C:\ProgramData\MySQL\MySQL Server X.X\my.ini(X.X代表MySQL版本号)
在配置文件中找到 [mysqld] 部分(如果没有就创建一个),然后添加或修改 max_connections 参数:
[mysqld]
max_connections = 新的连接数
客户端应用侧连接数
客户端与MySQL是基于TCP的长连接,而建立长连接是比较耗时的,所以一般会维护一个长连接池,当需要执行命令的时候就从长连接池中取出一条连接来使用。用完之后就塞回去,下次复用。
在配置文件中,一般都会有数据源的连接数,直接在配置文件中按照实际需求修改即可。
💡3、Buffer Pool设置过小
在MySQL的存储引擎层中,MySQL是将磁盘中的数据读取到Buffer Pool中进行操作的,那么如果Buffer pool设置过小,那么就会导致从磁盘中能够读取的数据有限,从而导致命中率下降。
修改Buffer pool大小
可以通过命令来修改:
set global innodb_buffer_pool_size= 大小
查看Buffer pool缓存命中率
但是当我们想要调整Buffer pool大小的时候,怎样知道Buffer pool的大小是否过小呢,那么可以通过检查命中率来进行分析。
检查命令:
show status like 'innodb_buffer_pool_%'
第一个参数表示读请求次数,第二个参数表示从物理磁盘中读请求的次数。那么就可以得到命中率
一般情况下命中率都会在99%以上,当降低到99%以下时,就需要调整大小了。