用同样1000行数据,一份按主键顺序插入一份打乱顺序插入,对比页分裂次数和真实的磁盘空间开销。
代码SET GLOBAL innodb_monitor_enable='index_page_splits'; -- 顺序插入:id按0,1,2...999的顺序 INSERT INTO seq_pk (id, pad) SELECT ... ORDER BY id; -- 乱序插入:同样的id集合,打乱顺序 INSERT INTO rand_pk (id, pad) SELECT ... ORDER BY RAND();
顺序插入1000行后: index_page_splits 真实增加了 14 次 乱序插入1000行后: index_page_splits 真实又增加了 19 次(累计33)
顺序插入的14次分裂,本质上是B+树往末尾不断追加数据、页面写满后真实必须再开一个新页的正常增长——这种"尾部分裂"代价最小,几乎是必然发生的。乱序插入额外多出来的19次,真实是往已经存在、中间已经写满的页面里插入新记录,导致那些页面被迫真实"从中间劈开"成两个更空的页面——这种分裂比尾部追加更贵,而且分裂出来的两个新页通常都只有一半左右是满的。
seq_pk.ibd(顺序插入): 344064 字节 (336KB) rand_pk.ibd(乱序插入): 425984 字节 (416KB) ← 真实多花了约24%的空间
每一步都是本文上面用真实计数器和磁盘文件跑出来的原始结果。
information_schema.INNODB_METRICS里的index_page_splits计数器