key_buffer_size是MySQL专用于缓存MyISAM表索引块的全局内存缓冲区,仅对MyISAM有效;它不缓存数据,但索引命中可大幅减少磁盘I/O,从而提升读取速度,需根据索引总大小设为80%~90%并重启生效。

MyISAM 表的高速读取依赖 key_buffer_size,不是“开启某个开关”就能生效,必须调大并验证命中率。
key_buffer_size 是什么,为什么它决定 MyISAM 读取速度
MyISAM 不用缓冲池(那是 InnoDB 的 innodb_buffer_pool_size),它靠 key_buffer_size 缓存索引块。数据文件(.MYD)仍走磁盘,但只要索引能从内存命中,定位数据行就快得多——这是 MyISAM 读性能的瓶颈所在。
默认值通常是 8M,对任何稍有规模的 MyISAM 表都远远不够。缓存不足时,Key_reads 会飙升,意味着每次查索引都在读磁盘。
- 该参数是全局、静态的,修改后必须重启 MySQL 才生效
- 它只缓存索引,不缓存数据;数据读取仍依赖操作系统页缓存或
read_buffer_size - 若你已全量迁移到 InnoDB,
key_buffer_size设为16M~32M即可,无需调大
怎么设合理的 key_buffer_size 值
不能拍脑袋填百分比。先看当前负载和内存余量:
- 执行
SHOW VARIABLES LIKE 'key_buffer_size';查当前值 - 执行
SHOW STATUS LIKE 'Key_read%';,计算缓存命中率:1 - (Key_reads / Key_read_requests);低于 0.999(即Key_reads / Key_read_requests > 0.001)就说明不够 - 用
free -h确认系统空闲内存,留至少 2G 给 OS 和其他进程 - 若 MyISAM 是主力引擎,且总索引大小在 2GB 以内,可设为物理内存的 20%~25%;例如 32G 内存机器,设
key_buffer_size = 6G
配置位置:编辑 /etc/my.cnf 或 /etc/mysql/my.cnf,在 [mysqld] 段下添加:
key_buffer_size = 6G
然后重启服务:sudo systemctl restart mysql。
容易被忽略的配套参数
单调 key_buffer_size 不够,MyISAM 读取还卡在其它环节:
-
read_buffer_size:影响全表扫描速度,每个线程独占,建议设为512K~2M(勿超 4M,否则高并发时内存爆炸) -
table_open_cache:MyISAM 表打开开销大,若频繁访问上百张 MyISAM 表,需调高(如2000),避免反复打开 .MYI 文件 -
sort_buffer_size:影响ORDER BY、GROUP BY性能,但它是 per-connection 的,设太大反而挤占内存,256K~1M较稳妥 - 禁用查询缓存(
query_cache_type = 0):MyISAM 表一旦有写入,整个表的查询缓存全失效,反而拖慢读——尤其在读写混合场景
验证是否真的变快了
改完别只看 SHOW VARIABLES,要盯住运行时指标:
- 持续观察
Key_reads是否下降:如果每秒仍 > 10,说明缓存还是不够或查询模式导致局部性差 - 对比慢查询日志中涉及 MyISAM 表的语句耗时,重点看
Using filesort或Using temporary是否减少 - 用
mysqladmin extended -r -i 1 | grep -E "Key_reads|Key_read_requests"实时看每秒变化
真正难的是:MyISAM 索引结构本身不支持行级锁和崩溃恢复,缓存再快,也掩盖不了引擎层的并发短板。如果你还在维护 MyISAM 表,key_buffer_size 是眼下最值得调的参数,但迁移至 InnoDB 才是长期解法。


















