MySQL性能优化学习——(四)性能优化总结

一、优化思路

性能优化的思路应该是什么样的?

说到性能调优,大部分时候想要实现的目标是让我们的查询更快。
一个查询的动作又是由很多个环节组成的,每个环节都会消耗时间,在第一篇 关于SQL 语句的
执行流程中已经分析过了。
想要减少查询所消耗的时间,就要从每一个环节入手。
 
 

二、连接——配置优化

第一个环节是客户端连接到服务端,连接这一块有可能会出现什么样的性能问题?

 
有可能是服务端连接数不够导致应用程序获取不到连接。比如报了一个 Mysql: error
1040: Too many connections 的错误。
可以从两个方面来解决连接数不够的问题:
1、从服务端来说,我们可以增加服务端的可用连接数。
如果有很多请求同时访问数据库,连接数不够的时候,我们可以:
(1)修改配置参数,增加可用连接数,修改max_connections的大小:
show variables like 'max_connections'; -- 修改最大连接数,当有多个应用连接的时候
 (2)或者即使释放不活动的连接。交互式和非交互式的客户端的默认超时时间都是28800秒,
8小时,我们可以把这个值调小。
show global variables like 'wait_timeout'; --及时释放不活动的连接,注意不要释放连接池还在使用的连接
 
2、从客户端来说,可以减少从服务端获取的连接数。
如果我们想要不是每次执行SQL都创建一个新的连接,应该怎么做?
我们可以引入连接池,实现连接的重用。
 
我们可以在哪些层面使用连接池?
ORM层面:MyBatis自带了一个连接池;
或者使用专业也连接池工具:阿里的Druid、Spring Boot 2.x版本默认的连接池Hikari、DBCP、C3P0;
 
当客户端改成从连接池获取连接之后,连接池的大小应该怎么设置呢?
常有一个误解,觉得连接池的最大连接数越大越好,这样在高并发时客户端可以获取更多的连接数,不需要排队。
这是错误的,连接池并不是越大越好,只要维护一定数量带下的连接池,其他客户端排队等待连接就可以了。
有点时候连接池越大,效率反而越低。
 
Druid的默认最大连接池大小是8,Hikari的默认最大连接池大小是10,为什么默认值都这么小?
在Hiari的github文档中,给出了一个PostgreSQL数据库建议的设置连接池大小的公式:

connections = ((core_count * 2) + effective_spindle_count)

它的建议是机器核数乘以 2 加 1。也就是说,4 核的机器,连接池维护 9 个连接就够了。
这个公式从一定程度上来说对其他数据库也是适用的。
 
为什么有的情况下,减少连接数反而会提升吞吐量呢?
为什么建议设置的连接池大小要跟 CPU 的核数相关呢?
每一个连接,服务端都需要创建一个线程去处理它。连接数越多,服务端创建的线程数就越多。
CPU的核数是有限的,执行多个线程,频繁切换(线程)上下文会造成比较大的性能开销。

 

不管是数据库本身的配置,还是按照这个数据库服务的操作系统的配置,

对配置进行优化,最终的目的都是使硬件本身的性能更好发挥,包括CPU、内存、磁盘、网络。

在之前的内容中也接触了很多的MySQL和InnoDB的配置参数,包括各种开关和数值的配置,

大多数参数都提供了一个默认值,比如默认的buffer_pool_size,默认的页大小,InnoDB的并发线程数等等。

这些默认配置可以瞒住大部分情况的需求,除非有特殊的需求,在清楚参数的含义时再去修改它。

修改配置的工作一般由专业的DBA完成。

这是官网系统的参数列表,需要时再做参考:

https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html

 

除了合理设置服务端连接数和客户端连接池大小外,还有哪些减少客户端和数据库服务端的连接数的方案呢?

可以引入缓存。

 

三、缓存——架构优化

3.1 缓存

在应用的并发数非常大的情况下,如果没有缓存,会造成两个问题:

一是会给数据库带来很大压力,二是对于应用来说操作数据的速度也会受影响。

可以采用第三方缓存来解决这个问题,比如 Redis。

运行独立的缓存服务,属于架构层面的优化

为了减少单台数据库服务器的读写压力,在架构层面还可以做哪些其他优化措施?

还可以采取主从复制、分库分表等方案。

 

四、优化器——SQL语句分析优化

优化器就是对我们的 SQL 语句进行分析,生成执行计划。
 

4.1 慢查询日志(slow query log)

我们可以通过慢查询日志知道服务中哪些SQL语句比较慢。
 
因为开启慢查询日志是有代价的(和bin log、optimizer-trace一样),所以默认关闭。
show variables like '%slow_query%';
 
除了这个开关,还有一个参数,控制执行多久的SQL才被记录到慢日志,默认是10秒:
show variables like '%long_query%';
可以直接动态修改参数(重启后失效):
set @@global.slow_query_log=1; -- 慢查询日志开关  1 开启,0 关闭,重启后失效
set @@global.long_query_time=3; -- mysql 默认的慢查询时间是 10 秒,另开一个窗口后才会查到最新值
 
或者修改配置文件 my.cnf,让配置永久生效。
以下配置定义了慢查询日志的开关、慢查询的时间、慢日志文件的存放路径。
slow_query_log = ON
long_query_time=2
slow_query_log_file =/var/lib/mysql/localhost-slow.log
 
show global status like 'slow_queries'; -- 查看有多少慢查询
show variables like '%slow_query%'; -- 获取慢日志目录
 
虽然有了慢日志,但是慢日志记录了所有超过设定值的慢查询,如何统计分析呢?总不能一条一条数。
MySQL提供了mysqldumpslow的工具,在MySQL的bin目录下。
例如:查询用时最多的20条慢SQL:
mysqldumpslow -s t -t 20 -g 'select' /var/lib/mysql/localhost-slow.log
 
Count:代表这条SQL被执行了多少次;
Time:代表执行的时间,括号内是累计时间;
Lock:代表锁定的时间,括号是累计锁定时间;
Rows:代表返回的记录数,括号是累计;
 
 

4.2 show profile

除了慢查询日志,还有show profile工具可以使用
https://dev.mysql.com/doc/refman/5.7/en/show-profile.html
 
 
show profile可以查看SQL语句执行的时使用的资源,比如CPU、IO的消耗情况。
 
查看是否开启:
select @@profiling;
若未开启则手动开启:
set @@profiling=1;
 
查看 profile 统计
show profiles;(命令最后带一个 s)
 
查看最后一个 SQL 的执行详细信息,从中找出耗时较多的环节(没有 s)。
show profile;
此处时间6.2E-5表示小数点左移 5 位,代表 0.000062 秒。
 
也可以根据 ID 查看执行详细信息,在后面带上 for query + ID。
show profile for query 1;
 
除了慢日志和 show profile,如果要分析出当前数据库中执行的慢的 SQL,还可以
通过查看运行线程状态和服务器运行信息、存储引擎信息来分析。
 

其他系统命令

show processlist 运行线程
show processlist;
用于显示用户运行线程。可以根据 id 号 kill 线程。
也可以查表,效果一样:
select * from information_schema.processlist;
 
Id : 线程的唯一标志,可以根据它 kill 线程
User : 启动这个线程的用户,普通用户只能看到自己的线程
Host : 哪个 IP 端口发起的连接
db : 操作的数据库
 
show status 服务器运行状态
SHOW STATUS 用于查看 MySQL 服务器运行状态(重启后会清空),有 session 和 global 两种作用域,格式:参数-值。
可以用 like 带通配符过滤。
SHOW GLOBAL STATUS LIKE 'com_select'; -- 查看 select 次数
 
show engine 存储引擎运行信息
show engine 用来显示存储引擎的当前运行信息,包括事务持有的表锁、行锁信息;
事务的锁等待情况;线程信号量等待;文件 IO 请求;buffer pool 统计信息。
例如:
show engine innodb status;
 
如果需要将监控信息输出到错误信息 error log 中(15 秒钟一次),可以开启输出。
show variables like 'innodb_status_output%';
-- 开启输出:
SET GLOBAL innodb_status_output=ON;
SET GLOBAL innodb_status_output_locks=ON;
 
其实很多开源的慢查询日志监控工具,他们的原理其实也都是读取的系统的变量和状态。
 
那么,现在我们已经知道哪些 SQL 慢了,为什么慢呢?慢在哪里?
 
MySQL 提供了一个执行计划的工具,
通过 EXPLAIN 我们可以模拟优化器执行 SQL 查询语句的过程,来知道 MySQL 是
怎么处理一条 SQL 语句的。通过这种方式我们可以分析语句或者表的性能瓶颈。
 

4.3 EXPLAIN 执行计划

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章