影响MySQL性能的环境变量详解

亡梦爱人 提交于 2020-09-26 08:20:06

本文目的: 本文旨在详细介绍影响MySQL性能的环境变量,让读者能够正确了解变量的含义,从而结合实际需求设置合理的值。
环境说明: MySQL版本:8.0.20 (文章内容基本适用MySQL5.7)
版权说明: 本文为博主原创,转载请注明出处。
原文地址: https://blog.csdn.net/qq_38688267/article/details/108317510


前言

查询环境变量

-- 查看所有环境变量
show variables;
-- 模糊查询环境变量
show variables like '%size%';

 

设置环境变量

-- 会话级设置,只会影响当前会话
set session join_buffer_size = 1024 * 256;

-- 全局设置
set global join_buffer_size = 1024 * 512;

 

重要变量介绍

全局变量

参数名 默认值 作用 说明
max_connections 151 允许的最大同时客户端连接数 这个根据业务需求和硬件条件设置,一般一两千即可,Linux系统最多支持10000。
join_buffer_size 262144
(256K)
用于普通索引扫描,范围索引扫描和不使用索引的联接的缓冲区的最小大小。 文章末尾会对该参数的取值详细介绍。传送门
thread_cache_size -1
(自动)
用于重用的缓存的线程数量,默认-1表示根据公式自动计算。 默认计算公式:8 + (max_connections / 100)
如果您的服务器每秒看到数百个连接,则应该合理增大该值。
thread_pool_size 16 线程池中的线程组数。注意: 这个参数要启用了线程池插件(商业产品 传送门)才可用。 一般设置服务器CPU数量的值即可。
tmp_table_size 16777216
(16M)
内存临时表最大大小,如果临时表超过该值,MySQL会自动将其转换到磁盘上 除非系统中有大量子查询或高级GROUP BY语句则可以增大该值;较少需要大空间临时表的语句则更改会话级变量即可。
transaction_prealloc_size 4096
(4K)
事务内存池初始值大小。每个事务都有一个内存池,各种与事务相关的分配都从该内存池获取内存。 该参数与下面的transaction_alloc_block_size参数结合配置,如果大事务较多,可以适量增加该值,减少malloc()执行次数。
transaction_alloc_block_size 8192
(8K)
增加需要事务的每个事务的内存池所用的字节数 对于由于没有足够的可用内存而无法从池中满足的每个分配,将执行malloc()增加该参数值的空间 。事务结束时,池再执行malloc()恢复成transaction_prealloc_size字节。
range_alloc_block_size 4096
(4K)
进行范围查询时分配的块的大小 如果范围查询比较多,可以适量增加该值
query_alloc_block_size 8192
(8K)
用于存储语句解析和执行期间创建的对象的内存块大小 如果复杂SQL比较多可以适量增大该值
query_prealloc_size 8192
(8K)
用于语句解析和执行的持久缓冲区的大小 如果复杂SQL比较多可以适量增大该值
lock_wait_timeout 31536000
(1年)
线程等待秒数 如果存在大量线程等待的SQL,可以尝试修改该值,但要做好异常捕捉,返回友好提示。
max_sort_length 1024
(1K)
排序数据值时使用的字节数 该参数及以下两个参数都与排序相关,文章末尾详细介绍。传送门
sort_buffer_size 262114
(256K)
执行排序时分配的缓冲区大小 该参数值最小也要为max_sort_length的15倍。
read_buffer_size 131072
(128K)
用于排序、INSERT INTO、嵌套查询时缓存的空间 如果进行多次顺序扫描,则可能需要增加此值。此变量的值应为4KB的倍数。如果将其设置为不是4KB倍数的值,则其值将四舍五入到最接近的4KB倍数。

 

Innodb引擎变量

参数名 默认值 作用 说明
innodb_thread_concurrency 0
(不限制)
InnoDB允许的最大线程数 达到限制后,会将其他线程放入“ 先进先出 ”(FIFO)队列中以等待线程。如果存在请求高峰,可以改成服务器CPU核数。
innodb_thread_sleep_delay 10000
(10ms)
InnoDB线程在加入InnoDB队列之前休眠的时间(以微秒为单位) InnoDB根据当前线程调度活动自动向上或向下调整innodb_thread_sleep_delay的值,这种动态调整有助于线程调度机制在系统负载较轻或系统接近满负荷运行时平稳运行。
innodb_adaptive_max_sleep_delay 150000
(150ms)
InnoDB线程休眠的最大微秒数 InnoDB根据当前线程调度活动自动向上或向下调整innodb_thread_sleep_delay的值,这种动态调整有助于线程调度机制在系统负载较轻或系统接近满负荷运行时平稳运行。
innodb_log_buffer_size 16777216
(16M)
InnoDB 用于写入磁盘上的日志文件 的缓冲区的大小 如果存在较多的大型事务或批量增删改操作,可以适量增加该值,避免在事务提交前将日志写入磁盘,并且减少磁盘I/O。
innodb_io_capacity 200 InnoDB后台任务的每秒I / O操作数(IOPS) 可以根据硬盘的IOPS数设置,如果硬件不达标,设置大了反而容易出问题!
innodb_io_capacity_max 2000 InnoDB后台任务的最大每秒I / O操作数(IOPS) 可以根据硬盘的突发IOPS数设置,如果硬件不达标,设置大了反而容易出问题!
innodb_write_io_threads 4 InnoDB中写入操作的I / O线程数 根据实际情况修改,如果是只读从库,则可将参数设置为0,或将innodb_read_only设置为1
innodb_read_io_threads 4 InnoDB中读取操作的I / O线程数 根据实际情况修改,如果是只负责写操作的主库,则可将参数设置为0

 

MyISAM引擎变量

参数名 默认值 作用 说明
key_buffer_size 8388608
(8M)
索引块的缓冲区的大小 结合实际情况设置即可,但最好不要超过服务器内存的25%
myisam_mmap_size 64位系统:
18446744073709551615
32位系统: 4294967295

用于内存映射压缩MyISAM文件的最大内存量(单位:byte) 如果使用许多压缩MyISAM表,则可以减小该值以减少发生内存交换问题的可能性。
read_rnd_buffer_size 262144
(256K)
当MyISAM在键排序操作之后按排序顺序从表中读取行时,将通过此缓冲区读取行,以避免磁盘查找。 将变量设置为较大的值可以大大提高ORDER BY 性能。但是,这是为每个客户端分配的缓冲区,因此不应将全局变量设置为较大的值。相反,仅在需要运行大型查询的那些客户端中更改会话变量。

 

补充说明

在DML语句中设置环境变量

       通过SELECT /*+ SET_VAR(variable_name = value) */ column_name FROM table_name 的方式在DML语句中设置环境变量。

-- 设置此次查询的 sort_buffer_size = 1M
SELECT 
	/*+ SET_VAR(sort_buffer_size = 1024 * 1024) */
	id 
FROM 
	sys_user 
ORDER BY
	id DESC
LIMIT 1000;

-- 同样也适用于UPDATE、DELETE和INSERT语句的SELECT子句中。
UPDATE
	sys_user
SET
	name = '博主真帅'
WHERE
	id IN (
		SELECT 
			/*+ SET_VAR(sort_buffer_size = 1024 * 1024) */
			id 
		FROM 
			sys_user 
		ORDER BY
			id DESC
		LIMIT 1000
	)

 

join_buffer_size取值

      join_buffer_size表示用于普通索引扫描,范围索引扫描和不使用索引的联接的缓冲区的最小大小。通常,获得快速联接的最佳方法是添加索引;如果无法添加索引,增加join_buffer_size的值可以获得更快的完成FULL JOIN,为两个表之间的每个FULL JOIN分配一个连接缓冲区。对于不使用索引的多个表之间的复杂联接,可能需要多个联接缓冲区。

      除非使用“Block Nested-Loop1或“批处理密钥访问”算法,否则将缓冲区设置为大于容纳每个匹配行所需的缓冲区不会有任何好处; 并且所有联接至少分配最小大小,所以将此变量设置为全局设置的代价很大。最好保持全局设置较小,并且仅在进行大联接的会话中将会话设置更改为较大的值,如果全局大小大于使用它的大多数查询所需的大小,则内存分配时间可能会导致性能大幅下降。

      建议通过一个系统中用的比较频繁比较具有代表性(复杂程度中等或中等偏下)的SQL进行测试,将join_buffer_size的值设置成最适合该SQL的大小。通过上文中介绍的 在DML语句中设置环境变量 的方法来找上述的代表性SQL或关联表比较多的SQL最合适的join_buffer_size的取值:

-- 开启profiling
set profiling = 1;

-- 执行SQL
SELECT /*+ SET_VAR(join_buffer_size=1024)*/ t1.name,  t2.name from insp_order t1  left join insp_order_point t2 ON t1.id = t2.order_id;
SELECT /*+ SET_VAR(join_buffer_size=1024 * 8)*/ t1.name,  t2.name from insp_order t1  left join insp_order_point t2 ON t1.id = t2.order_id;
SELECT /*+ SET_VAR(join_buffer_size=1024 * 64)*/ t1.name,  t2.name from insp_order t1  left join insp_order_point t2 ON t1.id = t2.order_id;
SELECT /*+ SET_VAR(join_buffer_size=1024 * 256)*/ t1.name,  t2.name from insp_order t1  left join insp_order_point t2 ON t1.id = t2.order_id;
SELECT /*+ SET_VAR(join_buffer_size=1024 * 512)*/ t1.name,  t2.name from insp_order t1  left join insp_order_point t2 ON t1.id = t2.order_id;

-- 查看执行情况
show profiles;

      通过返回结果可以看出,不同的join_buffer_size对SQL执行速度的影响还是比较大的,且示例SQL的最佳join_buffer_size的值在1024 * 1024即1M左右。
在这里插入图片描述
 



排序优化相关设置

      sort_buffer_size表示每个必须执行排序的会话都会分配此大小的缓冲区。sort_buffer_size并非特定于任何存储引擎,而是以一般方式进行优化。至少该sort_buffer_size值必须足够大以在排序缓冲区中容纳15个元组。另外,增加 max_sort_length的值可能需要增加sort_buffer_size的值。

      如果Sort_merge_passes2的值比较大,则可以考虑增加sort_buffer_size值以加快速度ORDER BY或GROUP BY使用查询优化或改进索引无法改善的操作。

      为了提高不能使用索引的ORDER BY的速度,请尝试:

  • 增加sort_buffer_size变量值。理想情况下,该值足够大的话就可以将整个结果集放入排序缓冲区(可以避免写入磁盘和合并过程)。
  • 存储在排序缓冲区中的列值的大小受max_sort_length系统变量值影响。例如,如果元组存储长字符串列的值,并且增加了max_sort_length的值,则排序缓冲区元组的大小也会增加,这时也需要增大sort_buffer_size
  • 增加read_rnd_buffer_size变量值,以便一次读取更多的行。

TIPS:
       1、为了获得用于文件排序操作的内存,从MySQL 8.0.12开始,优化器会根据需要增量分配内存缓冲区,最多达到sort_buffer_size系统变量指示的大小,而不是像MySQL 8.0.12之前那样预先分配固定数量的sort_buffer_size字节。这使用户可以将sort_buffer_size设置为较大的值以加快大型排序的速度,而不必担心小型排序会占用过多的内存。(但是可能具有弱多线程malloc的Windows上的多个并发排序不会有这个效果)
 
       2、从MySQL 8.0.22开始,使用select_into_buffer_size代替read_buffer_size执行SELECT INTO DUMPFILESELECT INTO OUTFILE语句时使用的缓冲区的值 。
 
       3、如果程序中出现异常:java.sql.SQLException: Out of sort memory, consider increasing server sort buffer size,则表示应该对该SQL增加sort_buffer_size的大小了;同理,如果程序中存在可能会出现大数据量排序的SQL则应该增加这条SQL的sort_buffer_size大小,规避由于分配的内存过小导致的异常。(这就是典型的测试环境OK,正式环境出问题的情况。。。)




 

总结

     · 本文中绝大部分关于变量的描述都摘抄自MySQL官方文档,MySQL的官方文档是我认为所有开源软件的文档中做的最详细最友好的了,而且还提供全文搜索功能!如果有关于MySQL的问题,强烈推荐各位读者看官方文档!
      · 本文只是列举了作者觉得对性能有影响的部分环境变量,后续还会继续完善,如果在文中有错误或解释不到位的,还请各位读者多多指点。

 


  1. 块嵌套循环,MySQL的一种优化策略,常出现在explain执行计划的extra列中,该优化策略在MySQL8.0.20版本中被移除。 ↩︎

  2. 状态变量,表示排序算法必须执行的合并通过次数,通过show status like 'Sort_merge_passes'查看。 ↩︎

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!