myisam前缀压缩索引通过只存储字符串键的公共前缀一次、后续仅存差异部分来减小索引文件体积,自动应用于char/varchar/text类型的索引列;innodb因需保障事务一致性、mvcc、聚簇索引有序性及崩溃恢复可靠性,放弃该压缩机制,选择以空间换确定性。

MyISAM前缀压缩索引是怎么工作的
MyISAM在构建B+树索引时,会对字符串类型的索引键做前缀压缩:比如连续几行的 title 值分别是 "MySQL索引优化"、"MySQL查询原理"、"MySQL事务隔离",MyISAM会把公共前缀 "MySQL" 只存一次,后续只存差异部分。这直接减小了索引文件(.MYI)体积,尤其对长文本或重复度高的字段效果明显。
这种压缩是存储引擎层实现的,不依赖用户显式指定,只要列类型是 CHAR、VARCHAR 或 TEXT,且建了索引,MyISAM就会自动启用。
InnoDB为什么不做前缀压缩
InnoDB的设计目标是强一致性与事务支持,所有数据和索引都按主键聚簇组织,索引页(16KB)内不仅要存键值,还要存完整的行记录或主键引用。如果引入前缀压缩:
- 会导致页内键值不再可直接比较(需解压后比),破坏B+树节点分裂/合并的稳定性
- 事务回滚、MVCC快照读时需保证索引键的原子性和可重现性,压缩会增加校验与恢复复杂度
- 聚簇索引中非叶子节点也要存键值用于导航,压缩会干扰“键有序”这一核心前提
所以InnoDB选择放弃压缩,用空间换确定性——所有键值以原始字节形式存储,保障并发、崩溃恢复和二级索引一致性。
你其实可以“模拟”前缀索引,但不是压缩
所谓“前缀索引”常被误认为“压缩”,其实更常见的是用户手动指定长度建索引,比如:
CREATE INDEX idx_title_prefix ON articles(title(10));
这个语法在InnoDB和MyISAM中都支持,但它只是截取前10个字符建索引,并不压缩存储;MyISAM在此基础上还能再做前缀压缩,而InnoDB只截取、不压缩。
注意点:
-
title(10)的选择必须基于实际数据分布,用SELECT COUNT(DISTINCT LEFT(title, 10)) / COUNT(*)看区分度,太短会导致大量重复键 - InnoDB中该索引无法用于
ORDER BY title或GROUP BY title,因为只存了前缀 - 如果查询条件是
WHERE title LIKE 'MySQL%',前缀索引仍有效;但WHERE title LIKE '%SQL%'就完全用不上
真正影响性能的往往不是压缩,而是存储引擎选型本身
现在几乎没人为了“前缀压缩”选MyISAM——它不支持事务、行锁、外键、崩溃恢复,且自MySQL 5.5起就不再是默认引擎。即便你真有超大文本字段需要高效前缀检索,也更推荐:
- 用InnoDB +
GENERATED COLUMN提取前缀并建索引 - 对高基数字段用全文索引(InnoDB从5.6起已支持
FULLTEXT) - 把检索逻辑下沉到应用层或引入Elasticsearch等专用方案
前缀压缩只是MyISAM时代为节省磁盘做的权衡,而InnoDB把资源让渡给了可靠性。要不要用,关键看你的数据能不能承受表级锁和无事务回滚——这点比索引省了几MB更重要。











