背景:
–每个索引有两个segment,用于管理叶子节点和非叶子节点
–每个segment包含多个extend,extend是一次文件扩展单元(64个Page)
–每个Page默认非压缩表为16K
相关Tips:
SPACE HEADER :表空间的第一个Page中,用于管理所有下述结构,
FILE SEGMENT INODE用于描述SEGMENT信息
每个EXTEND都对应一个EXTEND DESCRIPTOR,描述信息单独记录在一个Page中,占用40个字节,一个Page可以存放256个描述符,因此每隔(256*64)个Page会有一个单独的EXTEND DESCRIPTOR PAGE
SEGMENT INODE 用于管理其对应的SEGMENT信息,其中记录了该SEGMENT拥有的EXTEND的相关信息(以及该SEGMENT内的碎片Page信息) ,一个Page内可以存储的SEGMENT INODE个数为FSP_SEG_INODES_PER_PAGE(zip_size)。SEGMENT INODE的位置信息可以由BTREE的根节点中的SEGMENT HEADER得到。
问题:
每个SEGMENT通过一个宏FSEG_FILLFACTOR来决定什么时候进行段扩展,默认为8,也就是说,当一个SEGMENT中保留的Page数少于1/8时,就要对其进行扩展一个EXTEND,也就是64个Page。这个值是硬编码的,Facebook将其修改成可动态调整的值,根据其测试,可以减少不少空闲Page(达到10%)
上述逻辑的判断是在函数fseg_alloc_free_page_low中实现,当然比描述的更加复杂(一堆if else :-(..)
把Patch backport到了5.5.18,并跑了下test case,两个相同结构的表,load相同的数据。
innodb_segment_reserve_factor = 8 ibd文件大小为20971520
innodb_segment_reserve_factor = 500, ibd文件大小为23068672
大约减小了9%
有兴趣的同学可以从mysqlatfacebook在lauchpad上的Rev3814 来获得diff
更主要的是从学习该patch的过程中,顺便了解了一下fsp相关知识。