InnoDB辅助索引叶子节点存储主键值而非地址,导致单条索引记录更大,叠加16KB页限制、事务元数据及767字节单列索引上限,空间占用显著高于MyISAM;MyISAM索引仅存物理地址,无主键耦合与事务开销,结构更轻量。

因为 InnoDB 的辅助索引叶子节点存的是主键值,不是数据地址,索引条目本身更大,且受聚簇索引结构和页大小硬约束限制。
辅助索引存储内容不同导致空间占用翻倍
MyISAM 的辅助索引叶子节点只存 .MYD 文件里的行地址(通常是 4–6 字节),而 InnoDB 的辅助索引叶子节点必须存完整的主键值。如果主键是 BIGINT + CHAR(20) 组合,光主键就可能占 28 字节以上;再叠加索引字段本身长度、事务 ID、回滚指针等隐藏字段,单条索引记录体积远超 MyISAM。
这意味着:同样一个 VARCHAR(500) 字段建辅助索引,在 MyISAM 中可能只占几百字节,在 InnoDB 中实际写入索引页时可能突破 1KB —— 直接撞上单列索引 767 字节的默认软限制。
InnoDB 索引必须塞进 16KB 页里,且要预留空间
InnoDB 每个数据页固定 16KB,B+Tree 要求一个页至少存两条记录(否则退化为链表)。因此单条索引记录不能超过约 8KB;但还要考虑二级索引需携带主键、事务元数据、页内目录槽等开销,最终留给“可见索引键”的安全上限压到:
- 单列索引:默认
767字节(utf8mb4下 ≈ 191 字符) - 组合索引总和:不超过
3072字节(innodb_large_prefix=ON且ROW_FORMAT=DYNAMIC或COMPRESSED时才生效)
MyISAM 没有这种结构耦合,它的索引页只管索引键+地址,不涉及主键回查、事务控制流,所以单列索引能容忍到 1000 字节,组合索引也只卡总和 1000 字节。
创建时看似成功,其实悄悄截断了
当对 InnoDB 表执行 CREATE INDEX idx ON t (content(255)),如果 content 是 VARCHAR(2000),MySQL 不报错,但会静默转成前缀索引 —— 这不是宽容,是妥协。问题在于:
- 你本意可能是想加速
WHERE content = ?全值匹配,但前缀索引只能支撑LIKE 'xxx%'类查询 -
content列若大量值在第 256 字符后才出现差异(比如日志尾部时间戳),前缀索引将严重失效 - 这个截断行为不会写入
SHOW CREATE TABLE,只在SHOW INDEX的Sub_part列显示255,容易被忽略
真正棘手的不是限制数字本身,而是 InnoDB 把索引、主键、事务元数据全绑在一条物理记录里 —— 你改一个字段长度,可能牵出索引重建、主键重排、缓冲池淘汰一连串连锁反应。MyISAM 没这层耦合,所以“宽松”只是表象,InnoDB 的“严格”才是它保证事务与并发的代价。


















