MyISAM索引与数据分离是刻意设计:.MYI存B+Tree索引(叶子存磁盘地址),.MYD为纯堆表;查询需两次I/O,全表扫描快;不支持事务、行锁、崩溃恢复,故无需聚簇;写多并发高时性能下降,且不支持覆盖索引。
MyISAM 的索引和数据分离,不是设计缺陷,而是刻意为之的轻量级取舍:它压根不打算支持事务、行锁或崩溃恢复,所以不需要把数据和索引绑死在一块。
这种分离直接体现在文件职责上:
.MYI 文件只存 B+Tree 索引结构,叶子节点里塞的是地址(比如 0x1A2B3C 这样的磁盘偏移量),不是数据本身.MYD 文件就是个纯堆表,按插入顺序线性写入,不排序、不聚簇、不维护逻辑顺序SELECT * FROM t WHERE id = 123 时,先读 .MYI 找到地址,再跳转去 .MYD 读那一行 —— 两次 I/OSELECT * FROM t 全表扫描时,完全绕过 .MYI,直接顺序读 .MYD,速度极快InnoDB 必须聚簇,是因为它要靠主键组织物理存储来支撑 MVCC、行锁、崩溃恢复。MyISAM 没这些需求:
undo log / redo log,也不依赖“主键 ⇔ 物理位置”强绑定.MYD 文件,无需按主键精确定位某一行.MYI 损坏就只能 REPAIR TABLE,没机制重建地址映射写多或并发高时,问题立刻暴露:
UPDATE 或 DELETE 都得同时改 .MYI 和 .MYD,两个文件可能落在不同磁盘块,随机 I/O 增加INSERT 会锁住整个 .MYD,其他读写全部阻塞OPTIMIZE TABLE 实际是重建两个文件,期间表不可写,且临时空间暴涨SELECT name FROM t WHERE email = 'x@y',且 (email, name) 有联合索引,它仍要回 .MYD 查 —— 因为索引叶子节点里只有地址,不存任何列值这个“地址即一切”的模型,决定了 MyISAM 的能力边界:适合读多写少、可接受表锁、能容忍修复失败的场景。一旦写入压力上来,或者需要强一致性,分离结构就成了硬伤,而不是特色。