key_buffer_size仅影响myisam索引缓存,应根据实际索引大小(查information_schema)设为1.2–1.5倍,避免过大挤占内存;命中率低于0.999或key_reads/key_read_requests>0.001需优化,同时配齐table_open_cache等参数。

key_buffer_size 调不对,MyISAM 查询就快不起来——它只缓存 .MYI 索引块,不碰 .MYD 数据文件,命中率低于 0.999 就等于白配。
查当前值和缓存命中率是否够用
别猜,先看真实负载。执行这两条命令:
SHOW VARIABLES LIKE 'key_buffer_size';
SHOW STATUS LIKE 'Key_read%';
用 Key_reads / Key_read_requests 算出未命中率。比如 Key_reads = 1200、Key_read_requests = 1500000,那未命中率是 0.0008(0.08%),已经合格;如果超过 0.001(即千分之一),说明缓存太小,磁盘在频繁读索引。
- 命中率低 ≠ 一定要调大:也可能是索引设计差、查询没走索引,先
EXPLAIN看执行计划 -
Key_blocks_used接近Key_blocks_unused + Key_blocks_used总和,说明缓存几乎占满,但命中率又低,大概率是索引碎片或缓存被无效块塞住 - 刚重启 MySQL 时
Key_reads为 0 是正常的,得等业务流量跑一段时间再采样
设多少才合理:看内存余量,不看百分比拍脑袋
物理内存 32G 的机器,不能直接填 key_buffer_size = 8G。得先确认:
- 执行
free -h,留至少 2G 给 OS 和其他进程(比如 PHP、Nginx) - 用
du -sh /var/lib/mysql/*.MYI或SELECT SUM(index_length) FROM information_schema.tables WHERE engine='MyISAM';估算 MyISAM 总索引大小,设为它的 1.2–1.5 倍更稳妥 - 若总索引约 3.5G,
key_buffer_size = 4G比设成“25% 内存”(8G)更安全,避免挤占系统页缓存 - 64 位 Linux 上最大可设到 4GB 以上,但超过 4G 需确认 MySQL 版本 ≥ 5.0.52;32 位平台硬上限就是 4G
改完必须重启,动态 SET 只临时生效
SET GLOBAL key_buffer_size = 4294967296; 确实能立刻改,但 MySQL 重启后就回退到配置文件的值。生产环境必须写进配置:
[mysqld] key_buffer_size = 4G
然后执行 sudo systemctl restart mysql。重启后立刻验证:
- 再跑一遍
SHOW VARIABLES LIKE 'key_buffer_size';,确认输出是4294967296 - 检查
Key_blocks_used是否明显上升,说明新缓存已开始承载索引块 - 注意:如果
Key_blocks_unused仍极高(比如 > 90%),而命中率又不错,说明设大了,浪费内存
光调 key_buffer_size 不行,MyISAM 还卡在这些地方
MyISAM 读取不是单点瓶颈,这几个参数不配齐,key_buffer_size 再大也白搭:
-
read_buffer_size:每个线程全表扫描用的缓冲,设 512K~2M,别超 4M,否则并发高时内存爆炸 -
table_open_cache:MyISAM 打开表要加载 .MYI 文件头,上百张表建议 ≥ 2000,否则反复 open/close 成性能杀手 -
query_cache_type = 0:MyISAM 的查询缓存一写就全失效,读写混合场景下反而拖慢,关掉更稳 - 别混用引擎:InnoDB 表和 MyISAM 表共存时,
innodb_buffer_pool_size和key_buffer_size争内存,监控Com_select和Handler_read_*才知道哪边真在扛流量
真正难的是判断“是不是该继续用 MyISAM”——如果连 Key_blocks_used 都长期压满、Key_reads 居高不下,且业务已支持事务,换 InnoDB 可能比调参更治本。











