页分裂是InnoDB独有的B+树索引页满时拆分导致页内碎片的问题,MyISAM无此机制;InnoDB碎片难观测但严重影响查询性能,MyISAM碎片易量化但主要浪费磁盘空间。

页分裂是InnoDB独有的物理结构问题
InnoDB的页分裂发生在B+树索引页满时插入新记录,尤其是主键无序(如UUID、随机数)导致新行无法追加到末尾,必须拆分现有16KB页。每次分裂会生成新页,旧页留下空洞,长期积累形成页内碎片——这种碎片藏在.ibd文件内部,information_schema.TABLES.data_free常显示为0或几MB,完全不可信。
MyISAM没有“页分裂”概念:它的.MYI索引是纯B-Tree,.MYD数据文件是堆表,插入只追加或复用已删除行的位置,不会因索引顺序打乱物理布局。它的问题是“数据碎片”,表现为.MYD文件中大量空闲但不连续的小块,可通过OPTIMIZE TABLE重建.MYD/.MYI彻底清理。
- 页分裂只影响InnoDB,MyISAM根本不存在该机制
- InnoDB页分裂后,空洞保留在原页中供后续INSERT复用,但不会自动合并释放
- MyISAM的碎片是文件级空洞,
du -sh t.MYD能直观反映真实膨胀程度
MyISAM碎片更容易被观察和量化
MyISAM的碎片率可直接用SHOW TABLE STATUS LIKE 't'里的Data_free除以Data_length粗略估算;而InnoDB的Data_free字段基本无效——即使表已严重碎片化,它也可能恒为0或固定值(如4MB)。真正判断InnoDB碎片,得看du -sh /var/lib/mysql/db/t.ibd与逻辑大小data_length + index_length的差值,再结合row_util_ratio(实际行均长 / 理论行长)是否明显>1.5。
- MyISAM:碎片=文件系统可见的.MYD膨胀,
OPTIMIZE TABLE后du下降明显 - InnoDB:碎片=页内空洞+未purge的delete标记+页分裂残留,
du不变是常态 - 别信
information_schema.TABLES里任何InnoDB的Data_free数字
谁更严重?取决于你关心什么
如果关注**查询延迟恶化**:InnoDB页分裂更致命。它让原本顺序读变成随机I/O,B+树深度增加,二级索引回表跳转次数上升,且ORDER BY id DESC LIMIT 20这类分页越往后越慢——这不是缓存问题,是物理布局崩坏。
如果关注**磁盘空间浪费**:MyISAM碎片更“扎眼”。一个10GB的.MYD文件可能实际只存了3GB有效数据,du一看就知;而InnoDB同样逻辑数据量下,.ibd可能固定占12GB(含页头、空闲链表等),你删掉90%数据,du也不变。
- InnoDB碎片影响性能更深,但难诊断、难度量
- MyISAM碎片影响空间更直白,但对QPS冲击有限(除非全表扫描频繁)
- 高并发写入场景下,InnoDB页分裂叠加锁竞争,问题会被指数级放大
避免页分裂比清理碎片更重要
重建表(OPTIMIZE TABLE或ALTER TABLE t ENGINE=InnoDB)能暂时压平InnoDB碎片,但治标不治本。只要主键继续用UUID、更新频繁修改二级索引列、或innodb_file_per_table=OFF,下次写入高峰又会复发。
- 强制用自增
INT/BIGINT作主键,杜绝随机插入 - 批量UPDATE代替单行循环,减少索引页反复修改
-
innodb_file_per_table=ON必须开启,否则优化操作无效 - MyISAM已不适合现代业务,仅剩静态配置表等极低写入场景可考虑
页分裂不是“发生了就能修好”的问题,它是聚簇索引设计下持续磨损的物理过程。一旦发现row_util_ratio > 1.8或SELECT COUNT(*)耗时异常增长,说明底层页结构已经松动,这时候重建只是止痛,换主键才是根治。











