myisam索引仅缓存.myi文件中的索引页,数据文件.myd完全依赖os page cache,因此key_buffer_size调优有效而innodb_buffer_pool_size对其无效;其性能瓶颈常在os层而非mysql变量配置。

MyISAM 索引只缓存索引、不缓存数据,不是设计缺陷,而是明确的架构取舍:它把数据文件缓存完全交给操作系统(OS)完成,自身只管理索引页的缓存。这意味着你调优 key_buffer_size 有效,但调大 innodb_buffer_pool_size 对 MyISAM 完全无效。
MyISAM 的 key_buffer_size 只管 .MYI 文件
MyISAM 把索引单独存放在 .MYI 文件里,所有 B-tree 索引节点(包括主键和二级索引)都走这个缓冲区。它的作用非常聚焦:
-
key_buffer_size值过小会导致频繁磁盘读取索引块,Key_reads和Key_read_requests比值升高(比如 > 0.01)就是明显信号 - 该缓冲区是全局共享的,不按表或线程划分;即使只查一张小表,也可能被其他大表的索引扫描挤占
- 它不感知数据行位置——查到索引叶子节点后,得到的是
.MYD文件中的字节偏移量,后续读数据完全依赖 OS 文件系统缓存
数据文件(.MYD)靠操作系统缓存,不受 MySQL 控制
MyISAM 的数据行存在 .MYD 文件中,MySQL 进程从不主动缓存这部分内容。每次需要读某一行,都是通过系统调用(如 read())向内核发起请求,由 OS 决定是否命中 page cache。
- 这意味着你观察
Handler_read_rnd或Handler_read_first高,并不能直接归因于 MySQL 缓存配置——可能是 OS page cache 不足、或.MYD文件碎片化严重 - 如果你在容器或低内存环境运行 MySQL,OS 可能优先回收
.MYD对应的 page cache,导致看似“缓存命中率低”,实则和 MySQL 配置无关 - 执行
sudo drop_caches=3后首次查询变慢,且恢复缓慢,基本可确认是 OS 层面的缓存冷启动问题,不是 MySQL 自身没缓存
InnoDB 的 buffer pool 是全链路接管,MyISAM 没有等价物
很多人误以为调大 innodb_buffer_pool_size 能“顺便”提升 MyISAM 性能,这是典型混淆。InnoDB 的 buffer pool 同时管理索引页(.ibd 中的 B-tree 节点)和数据页(聚簇索引的叶子行),而 MyISAM 根本没有对应的统一缓存机制。
- MyISAM 没有类似
buffer pool的概念,也没有innodb_old_blocks_pct、innodb_random_read_ahead这类面向数据页的调优参数 - 如果你混合使用 InnoDB 和 MyISAM 表,
key_buffer_size和innodb_buffer_pool_size必须独立评估——前者吃内存但只服务索引,后者吃更多内存但覆盖索引+数据 - MySQL 8.0 已全面废弃 MyISAM 系统表(如
mysql.help_topic等),仅保留兼容性支持;新项目继续用 MyISAM,等于主动放弃 buffer pool 级别的数据局部性优化能力
真正容易被忽略的点在于:MyISAM 的“缓存表现”高度依赖 OS 状态和文件系统行为,而不是 MySQL 的变量。监控时若只盯 Key_cache_* 状态变量,却忽略 /proc/meminfo 中的 Cached 和 Buffers,很容易误判瓶颈所在。











