它的建议是机器核数乘以 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 : 启动这个线程的用户,普通用户只能看到自己的线程
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 执行计划