.myi文件存储b+tree索引,叶子节点存数据行在.myd中的磁盘地址;.myd文件为堆表,按插入顺序线性存储原始数据,无排序与聚簇结构。

MyISAM 的索引和数据分开存储,不是设计失误,而是由它的存储引擎定位决定的:它压根不支持事务、行锁或崩溃恢复,目标就是「快读 + 简单结构」。这种分离直接服务于它的核心能力——全表扫描和并发读。
MyISAM 的 .MYI 和 .MYD 文件各管什么?
.MYI(索引文件)只存 B+Tree 结构的索引项,每个叶子节点里不是数据本身,而是一个磁盘地址(即 .MYD 文件里的偏移量);.MYD(数据文件)是纯粹的堆表(heap table),按插入顺序线性存放记录,不按主键排序,也不维护任何逻辑顺序。
这意味着:
-
SELECT * FROM t WHERE id = 123要先查.MYI找到地址,再跳转到.MYD读那一行 —— 两次 I/O -
SELECT * FROM t全表扫描时,根本不用碰.MYI,直接顺序读.MYD即可,非常快 - 没有聚簇概念,
PRIMARY KEY和普通INDEX在结构上完全等价,都是二级索引
为什么不用像 InnoDB 那样把数据塞进 B+Tree 叶子节点?
InnoDB 必须聚簇,是因为它要靠主键组织整张表、支撑 MVCC、实现行锁和崩溃恢复 —— 这些都依赖「数据物理位置与主键逻辑顺序强绑定」。而 MyISAM 没这些需求:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 不支持事务 → 不需要 undo log、redo log,也无需通过聚簇结构保证一致性
- 只支持表锁 → 不需要按主键定位行来加锁
- 崩溃后无法安全恢复 → 数据文件损坏就真丢了,没机制重建索引与数据映射关系
所以它选择最轻量的解耦:索引归索引,数据归数据,各自独立管理,增删改只需更新对应文件,逻辑清晰、实现简单。
这种分离在实际使用中会暴露哪些问题?
分离带来的代价,在写多或并发高的场景下立刻显现:
- 每次
UPDATE或DELETE都要同时修改.MYI和.MYD,但两个文件可能落在不同磁盘块,增加随机 I/O - 没有行级锁,
INSERT时整个.MYD文件会被表锁住,其他查询/写入全部阻塞 -
OPTIMIZE TABLE实际是重建.MYD和.MYI两个文件,期间表不可写,且会产生大量临时磁盘空间 - 如果
.MYI损坏而.MYD完好,索引全丢,只能REPAIR TABLE—— 但修复成功率低,且不保证数据一致性
真正容易被忽略的点是:MyISAM 的「索引即地址」模型,使得它无法支持覆盖索引的高效利用。比如 SELECT name FROM t WHERE email = 'x@y',即使 email 和 name 都建了联合索引,MyISAM 仍要回表查 .MYD —— 因为它的索引叶子节点里只有地址,不存任何数据列值。这点和 InnoDB 的二级索引能存主键值、进而支持部分覆盖完全不同。










