WiredTiger存储引擎之一:基础数据结构分析
前言
从本月起,我们将从逻辑正确、内容完整的角度全面介绍WiredTiger存储引擎,推出WiredTiger存储引擎系列文章。由于源码体量很大,通读工作量巨大,细节之处如有问题和错误,欢迎大家指出。
典型的B-Tree结构 WT在磁盘上的数据结构 WT在内存上的数据结构 Page上的数据结构
典型B-Tree数据结构
图:典型的B-Tree数据结构
磁盘上的基础数据结构
图:WiredTiger数据文件在磁盘上的存储结构
内存上的基础数据结构
图:WiredTiger在内存上的数据结构
内存里面B-Tree包含三种类型的page,即rootpage、internal page和leaf page,前两者包含指向其子页的page index指针,不包含集合中的真正数据,leaf page包含集合中的真正数据即keys/values和指向父页的home指针;
内存上的leaf page会维护一个WT_ROW结构的数组变量,将保存从磁盘leaf page读取的keys/values值,每一条记录还有一个cell_offset变量,表示这条记录在page上的偏移量;
内存上的leaf page会维护一个WT_UPDATE结构的数组变量,每条被修改的记录都会有一个数组元素与之对应,如果某条记录被多次修改,则会将所有修改值以链表形式保存。
内存上的leaf page会维护一个WT_INSERT_HEAD结构的数组变量,具体插入的data会保存在WT_INSERT_HEAD结构中的WT_UPDATE属性上,且通过key属性的offset和size可以计算出此条记录待插入的位置;同时,为了提高寻找待插入位置的效率,每个WT_INSERT_HEAD变量以跳转链表的形式构成。
图:跳转链表示意图
假如现在插入一个16,终结果如下:
图:跳转链表插入一个元素16后的示意图
如果是一个普通的链表,寻找合适的插入位置时,需要经过:
开始结点->2->5->8->10->20的比较;
对于跳转链表来说只需经过:开始结点->5->10->20的比较,可以看到比在普通链表上寻找插入位置时需要的比较步骤少,所以,通过跳转链表的数据结构能够提升插入操作的效率。
page的其它数据结构
对于一个面向行存储的leaf page来说,包含的数据结构除了上面提到的WT_ROW(keys/values)、WT_UPDATE(修改数据)、WT_INSERT_HEAD(插入数据)外,还有如下几种重要的数据结构:
WT_PAGE_MODIFY:
保存page上事务、脏数据字节大小等与page修改相关的信息;
read_gen:
page的read generation值作为evict page时使用,具体来说对应page在LRU队列中的位置,决定page被evict server选中淘汰出去的先后顺序。
WT_PAGE_LOOKASIDE:
page关联的lookasidetable数据。当对一个page进行reconcile时,如果系统中还有之前的读操作正在访问此page上修改的数据,则会将这些数据保存到lookasidetable;当page再被读时,可以利用lookasidetable中的数据重新构建内存page.
WT_ADDR:
page被成功reconciled后,对应的磁盘上块的地址,将按这个地址将page写到磁盘,块是小磁盘上文件的小分配单元,一个page可能有多个块。
checksum:
page的校验和,如果page从磁盘读到内存后没有任何修改,比较checksum可以得到相等结果,那么后续reconcile这个page时,不会将这个page的再重新写入磁盘。
专栏作者:郭远威
MongoDB中文社区委员,长沙分会主席
《大数据存储MongoDB实战指南》作者
大数据架构师,通信行业业务架构与数据迁移专家
相关文章