supremum slot owned
1到8条记录
普通slot owned
4到8条记录
从上可以看出,slot指向的rec中的owned代表的是向前有多少个rec属于这个slot管辖,中间被管辖的rec的owned = 0。通过directory的二分查找只能查到对应记录所属的slot,还需要通过owned内部的二分查找才能精确定位到对应的记录。这种设计的做法可以减小directory对page空间的占用,又能有很好查找的效率。关于slot相关的函数说明: page_dir_split_slot slot分裂函数,当一个slot管辖的范围内插入新的记录后超出其最大管理的记 录数,就会对其进行平均范围分裂。 page_dir_balance_slot slot均衡函数,当一个slot管辖的范围内有记录删除后,其管理的记录数小于 它最小范围,就会和邻近的slot做均衡。 不管是均衡还是分裂,都是最大范围提高directory存储空间效率和记录查找效率。
3.4index page结构关系图
4页的操作
innodb的index page对记录的操作主要有3种:查找记录、插入记录、删除记录。关于page的操作实现在page0cur.* 当中,在这些操作的中,innodb定义了一个page_cur_t,也就是page的游标,它是个逻辑概念的游标,只在内存中 有效。这个page cur是指向当前操作的记录。定义如下:typedef struct page_cur_struct
{
byte* rec; /*游标记录的指针*/
}page_cur_t;因为所有的page操作必须将page从物理磁盘读入到内存中进行逻辑页的构建,再使用page_cur来进行查找、插入、删除操作。
4.1查询操作
我们知道在innodb的B+Tree索引搜索中,只能找到对应记录所在的index page,那么找到page后,会在页中进行记录查找,这个页内查找过程如下: 1.先通过key在page的directory slots中进行二分查找,找到key对应的slot 2.因为slot是管理多个记录(普通的slot owned = [4,8]),所以会再根据KEY在对应的slot管理的记录中一次二分查找,直到找到记录为止。 页内查找的实现在page0cur.c的page_cur_search_with_match函数当中,这个函数除了返回查找的记录以外,还会记录二分查找过程中匹配的字节数和经过的跳数。值得注意的是这个函数支持四种模式的查找,分别定义如下:#define PAGE_CUR_G 1 /*大于查询*/
#define PAGE_CUR_GE 2 /*大于等于查询*/
#define PAGE_CUR_L 3 /*小于查询*/
#define PAGE_CUR_LE 4 /*小于等于查询*/
4.2插入操作
在记录插入之前,会通过要插入记录KEY找到要插入的位置,查找的模式是PAGE_CUR_LE,具体步骤如下: 1.通过记录的key和记录查找函数查找要插入的位置(操作page cur指向插入记录的前一个记录) 2.修改前后记录的关联关系和插入记录的关联关系 3.修改page游标方向计数器、page last insert 4.修改所在的slot的owned数值,如果超出范围,进行split slot 5.因为插入记录是对页进行修改,所以记录插入记录的mtr log。以便异常时对页的恢复。 插入记录的mtr log构造比较复杂,以下是它的结构示意图:
vc+jrNXiuPax5MG/vs3Kx7LlyOu1xLzHwry6zcbkx7DD5rXEvMfCvLTTv6rKvM671sPP4M2s19a92sr9o6zV4tH5cmVjIGRhdGHKx7TmtKLBy9Pr1q7HsLzHwryyu82stcTK/b7doaMK0rvM9bzHwry1xLLlyOvKvtLizbyjugo8aW1nIHNyYz0="https://www.cppentry.com/upload_files/article/57/1_0gji8__.jpg" alt="\">
整记录插入过程在page0cur.c中的page_cur_insert_rec_low函数中实现的。
4.3删除操作
记录删除也是首先会通过删除记录的key或者记录地址来确定操作page cur.操作步骤如下: 1.通过记录信息确定page cur 2.添加一条删除记录的mtr log 3.将记录前后对应关联关系进行删除和更改 4.设置page last insert和其他的头信息(n _rec) 5.将记录插入到body header free列表的起始位置,并修改PAGE_GARBAGE 6.设置所在slot的owned,如果小于管辖范围的最小值,进行slot的均衡化。 删除的mtr log格式如下:
删除记录示意图:
5.小结
innodb的index page结构是一个高效利用空间的存储结构,不仅考虑到查询的速度,也考虑了合理的利用存储空 间的存储效率。innodb在这两者之间找到了比较好的平衡点。页除了提供基本的插入删除查询操作外,还提供批量 拷贝记录、批量删除记录等功能。当这些都是基于基本的插入删除操作之上的。批量操作函数如下:| page_copy_rec_list_end |
将page中的rec之后的记录全部复制到new page,包括rec |
| page_copy_rec_list_start |
将page中在rec之前的记录全部拷贝到new page当中,不包括rec |
| page_delete_rec_list_end |
将page中的rec之后的记录全部删除,包括rec |
| page_delete_rec_list_start |
将page中在rec之前的记录全部删除,不包括rec |
| page_move_rec_list_end |
将page中rec之后的记录全部move到new page中,包括rec,这些记录在page是被删除的 |
| page_move_rec_list_start |
将page中rec之前的记录全部move到new page中,不包括rec,这些记录在page是被删除的 |