B-Trees
日志结构的索引虽然目前得到认可,但是它不是最常见的索引类型,应用最广泛的索引类型是B-Tree。
在几乎所有数据库中B-Tree仍然是索引的标准实现。许多非关系数据库也在用它。
像SSTable一样,B-Tree把键值对按照key排序,这样就保证了键值对的高效查询和范围查询(range query)。但是这也是相似之处的结束点:B-Tree的设计哲学非常之不同。
日志结构的索引把数据库划分成可变尺寸的segment,一般几M或更多。按照顺序写每一个segment。与之相反的是,B-Tree把划分成固定尺寸的block或page,一般4K或更多,一次读或写一个page。这种设计与硬件对应的很密切,因为磁盘也是按照固定的尺寸排列的。
可以通过地址或者位置可以找到一个具体的page,同时一个page也可以引用另外一个page,和指针类似,但是是在磁盘上而不是在内存中。我们可以用这些page的引用来构建一棵树。如图3-6
B-Tree中一个page被设计为root,查询的时候从root开始。每个page包含几个key和子page的reference,每个子page负责一个连续key的范围。reference之间的key表示范围边界。
B-Tree中一个page中的子page的reference的数量叫做branching factor。实战中,branching factor取决于存储reference和range边界的所需要的空间,通常是几百。
如果你想要更新key对应的值,搜索到叶子page后,直接修改,然后写回磁盘就可以了。如果想要添加key,找到范围包含那个key的page,添加就行了。如果page空间不足,就把那个page分成两半,父亲page被更新,并且负责新的key范围的分支。
这个算法确保了树一直保持平衡:一个n个key的B-Tree,其深度是O(logn)。大部分数据库可以容纳3或4层的B-tree。所以查询的时候不用遍历很多的reference。(一个四层4KB的page,branching factor是500的B-tree可以存储高达256TB的数据)