【MySQL笔记】MySQL有些参数的学习记录-sort_buffer_size

本文详细解读sort_buffer_size参数对MySQL ORDER BY性能的影响,提供生产环境下的配置建议,并附带官方文档链接。

 

上干货:关注sort_buffer_size的参数,

sort_buffer_size: 是 MySQL 执行排序使用的缓冲大小。 如果想要增加 ORDER BY 的速度,首先看是否可以让 MySQL 使用索引而不是额外的排序阶段。 如果不能, 可以尝试增加sort_buffer_size 变量的大小。

以上几张图摘自不知名的大佬,以及第一张图是来自mysql5.7参考手册。 以上以上,前人栽树,后人乘凉。

生产一般配置:

[mysqld]

sort_buffer_size=8m

myisam_sort_buffer_size=32m

[myisamchk]
key_buffer = 512M
sort_buffer_size = 512M
read_buffer = 8M
write_buffer = 8M

官方文档:https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sort_buffer_size

 

==================End====================

<think>我们正在为MySQL 8.0.39在32G内存的服务器上配置以下缓冲区参数- sort_buffer_size - join_buffer_size - read_buffer_size - read_rnd_buffer_size 这些参数都是每个线程(连接)单独分配的,因此设置过大在高并发下可能导致内存耗尽。我们需要在全局设置中找到一个平衡点。 ### 一、参数含义及默认值 1. **sort_buffer_size** - 用于排序操作(如ORDER BY、GROUP BY)的缓冲区大小。 - 默认值:256KB(MySQL 8.0)[^1]。 2. **join_buffer_size** - 用于无法使用索引的JOIN操作(Block Nested Loop)或当优化器选择使用此缓冲区时。 - 默认值:256KB(MySQL 8.0)[^1]。 3. **read_buffer_size** - 用于顺序扫描表时的缓冲区大小(如全表扫描)。 - 默认值:128KB(MySQL 8.0)[^1]。 4. **read_rnd_buffer_size** - 用于按非索引顺序读取行时的缓冲区(如排序后的结果集)。 - 默认值:256KB(MySQL 8.0)[^1]。 ### 二、设置原则 - **全局设置不宜过大**:每个连接都会独立分配这些内存,高并发时总内存消耗为:`参数值 × 最大连接数`。 - **优先优化索引**:这些缓冲区主要用于无法使用索引的操作,优化索引比调大缓冲区更有效。 - **会话级调整**:对于特定需要大缓冲区的查询,在会话中临时设置(如:`SET SESSION sort_buffer_size=2M;`)。 ### 三、推荐配置(32G内存服务器) 根据经验,建议如下(假设最大连接数`max_connections`为200): 1. **计算总内存约束**: 这些缓冲区总内存应不超过物理内存的10%~15%(防止OOM)。 32GB的10% = 3.2GB ≈ 3200MB。 按200连接计算:每个连接可分配约16MB(3200MB/200)。 2. **具体参数推荐**: - **`sort_buffer_size`**: 通常设置为1MB~4MB。推荐: ```ini sort_buffer_size = 2M # 默认256KB,提升至2MB ``` 理由:排序操作常见,但过大会导致内存碎片[^2]。 - **`join_buffer_size`**: 由于MySQL 8.0优先使用Hash Join,此参数作用降低。推荐: ```ini join_buffer_size = 2M # 默认256KB,提升至2MB ``` 注意:若存在大量无索引JOIN,可临时在会话中调大至4MB~8MB。 - **`read_buffer_size`**: 顺序扫描较少时保持默认,若全表扫描频繁可微增: ```ini read_buffer_size = 1M # 默认128KB,提升至1MB ``` - **`read_rnd_buffer_size`**: 通常与`read_buffer_size`接近,推荐: ```ini read_rnd_buffer_size = 2M # 默认256KB,提升至2MB ``` 3. **验证总内存消耗**: 按200连接计算: - sort_buffer: 2MB × 200 = 400MB - join_buffer: 2MB × 200 = 400MB - read_buffer: 1MB × 200 = 200MB - read_rnd_buffer: 2MB × 200 = 400MB **总计**:1400MB < 3200MB(安全)。 ### 四、关键注意事项 1. **监控实际使用**: 运行后检查状态变量: ```sql SHOW GLOBAL STATUS LIKE '%buffer_size%'; ``` 观察`Sort_merge_passes`(若值大,可适当增加`sort_buffer_size`)[^1]。 2. **优先使用索引**: - 为JOIN字段、WHERE条件字段添加索引。 - 避免全表扫描。 3. **InnoDB缓冲池独立设置**: `innodb_buffer_pool_size`(数据/索引缓存)应占物理内存的70%~80%: ```ini innodb_buffer_pool_size = 24G # 32GB的75% ``` 4. **高并发场景**: 若连接数远大于200,需按比例降低缓冲区大小(如连接数=500,则所有参数减半)。 ### 五、配置文件示例 ```ini [mysqld] # 缓冲区设置 sort_buffer_size = 2M join_buffer_size = 2M read_buffer_size = 1M read_rnd_buffer_size = 2M # InnoDB核心设置 innodb_buffer_pool_size = 24G innodb_log_file_size = 2G # 连接控制 max_connections = 200 ``` ### §§相关问题§§ 1. **如何监控MySQL各缓冲区的实际内存使用情况?** 2. `innodb_buffer_pool_size` 设置过大是否会导致内存浪费? 3. 当出现大量排序操作时,除了调大`sort_buffer_size`还能如何优化? 4. MySQL 8.0的Hash Join算法在哪些场景下会失效? 5. 如何根据`SHOW GLOBAL STATUS`的输出调整缓冲区参数? [^1]: MySQL官方文档:缓冲区参数定义与监控 [^2]: 《高性能MySQL》内存参数优化章节</think>以下是为 MySQL 8.0.39 在 32GB 内存服务器上的缓冲区参数配置建议,基于最佳实践和内存分配原则: ### 一、核心缓冲区配置建议 | **参数** | **推荐值** | **说明** | |------------------------|------------|--------------------------------------------------------------------------| | `innodb_buffer_pool_size` | 24G | 应占物理内存的70-80%,缓存数据和索引的主区域[^2] | | `sort_buffer_size` | 2-4M | 每个排序线程专用,避免超过8M(过高会导致内存浪费) | | `join_buffer_size` | 2-4M | MySQL 8 优先使用Hash Join,此参数作用降低,会话级按需调整[^1] | | `read_buffer_size` | 1-2M | 顺序扫描缓冲区,全表扫描频繁时可设为2M[^1] | | `read_rnd_buffer_size` | 1-2M | 随机读缓冲区,通常与`read_buffer_size`相当 | > 💡 **总内存计算**: > 24G (InnoDB缓冲池) + (4M+4M+2M+2M)×200连接 ≈ 24G + 2.4G = 26.4G < 32G(安全边界) ### 二、配置文件示例 (`my.cnf`) ```ini [mysqld] # 核心内存配置 innodb_buffer_pool_size = 24G innodb_log_file_size = 2G # 线程级缓冲区设置 sort_buffer_size = 4M join_buffer_size = 4M read_buffer_size = 2M read_rnd_buffer_size = 2M # 连接控制 max_connections = 200 thread_cache_size = 20 # 8.0优化项 optimizer_switch = 'hash_join=on' ``` ### 三、关键配置原则 1. **InnoDB优先** 32G内存中分配24G给`innodb_buffer_pool_size`,确保热点数据内存命中率>95%[^2] 2. **线程缓冲区节制** ```mermaid graph LR A[单个连接内存需求] --> B((sort_buffer)) A --> C((join_buffer)) A --> D((read_buffer)) A --> E((read_rnd_buffer)) F[200连接] --> G[4M+4M+2M+2M=12M/连接] G --> H[200*12M=2.4G] ``` 总内存消耗需满足: $$24G + (max\_connections \times \sum buffers) < 32G$$ 3. **动态调整策略** ```sql -- 对特定大查询临时调整 SET SESSION sort_buffer_size = 8*1024*1024; SELECT ... ORDER BY ...; ``` ### 四、验证与监控 ```sql /* 检查实际内存分配 */ SHOW VARIABLES LIKE '%buffer_size%'; /* 监控性能指标 */ SHOW STATUS WHERE Variable_name IN ( 'Sort_merge_passes', -- 若>0需增加sort_buffer 'Handler_read_rnd_next' -- 全表扫描次数 ); ``` ### 五、注意事项 1. 避免全局设置过大缓冲区导致OOM(如设置`join_buffer_size=128M`时,200连接将消耗25.6G) 2. MySQL 8.0的Hash Join在多数场景优于BNLJ,优先保证`optimizer_switch=hash_join=on` 3. 全表扫描频繁时,优化索引比调大`read_buffer_size`更有效 > 📌 **最终建议**:先用推荐值运行1周,根据`SHOW STATUS`指标微调。优先优化查询和索引,其次调整缓冲区。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值