本篇较长较枯燥,请保持耐心看完。git
前面两章介绍了一下倒排索引以及倒排索引字典的两种存储结构,分别是跳跃表和哈希表,本篇咱们介绍另外一种数据结构,他也被大量使用在信息检索领域,我在github
上实现的搜索引擎的词典也是用的这个数据结构,它就是B+树。github
首先,咱们看看什么是树,树是程序设计中一个很是基础的数据结构,记得大学时候的数据结构课,链表,栈,队列,而后就是树了,虽然那时候想必你们都被前序遍历,中序遍历,后序遍历折腾过,不过树确实是一种很是有用的数据结构。算法
上一篇咱们说过,表2的第一列首要解决的问题就是能快速找到对应的词,而后找到对应词的倒排列表,除了跳跃表和哈希表,B+树也能知足条件,B+树是B树的变种,咱们B树咱们就不看了,感兴趣的你们能够直接去google一下,咱们主要讲的是B+树,下图就是一个3层的B+树,我画出来可能和你们搜出来的有点出入,可是不要紧,关键B+树这种数据结构的思想你们了解了就行。sql
假设咱们有一组数字 34,40,67,5,37,12,45,24,那么,把他们存成B+树就是下图这个样子。数据库
咱们很明显看到几个特色编程
我尽可能的把B+树说简单点,网上的资料也好,查书也好,看上去都挺复杂的,首先咱们看看怎么创建这棵树,我尽可能用图了,少一些文字也好理解一点,前方大量图预警。数组
首先,咱们的数组是34,12,5,67,37,40,45,24服务器
####第一步,初始化B+树,是这样子的微信
这时候,啥也没有,可是占用了两个节点,标识为无的,表示这个元素无心义,标记为NULL表示无穷大cookie
####第二步,插入34这个元素,那么图变成这样子
咱们看到,插入的过程是顺着指针一直走到叶子节点,发现叶子节点是空的,而后把元素插入到叶子节点的头部,而后返回上一级节点,将NULL后移,而后把第一个元素置为他的子节点的最大值,请记住这句话:置为他的子节点的最大值
####第三步,接着插入第二个元素12
这个步骤复杂一点
####第四步,而后是插入5
这一步更复杂一点,产生了分裂
####第五步,接着咱们插入67
这一步比较简单
####第六步,咱们插入37,插完这个后面的我就不写了,感兴趣能够本身画一下
这一步复杂了,这一步不只分裂了,并且分裂了两次,而且层数增长了一层
按照这六步,前5个元素就插入到B+树中了,后面的步骤您能够本身走一走,B+树基本的思想就是这样子的,可能我没有按照教科书上的作法来讲,但这并不影响你们的理解,我相信看完了之后虽然你脑子里没有标准的算法步骤,但应该有个大体的轮廓了,只不过须要本身再仔细想一想步骤。
####总的来讲,B+树的插入步骤无外乎如下几个步骤
查找操做和更新操做几乎同样,就是更新操做的前面两步,就不说了。
通常的更新的时候也是先查找,找到叶子节点,再更新,而后顺着指针往上走继续分裂,这个顺着往上走通常状况下首先想到的是双向指针,可是双向指针分裂的时候有点麻烦,须要把两个指针都从新指新节点,我实现的时候用了一个栈,查找叶子节点的时候把通过的节点依次压栈,到达叶子节点后,完成插入操做,往上遍历的时候依次把栈弹出来就好了,少了一个指针。
回到上一篇说的那个表2的第一列,若是是那个表的话,用这个B+树加上倒排链的话,最后的数据结构就长成这样子了(字符串的大小我随便写的,中文的顺序排列哥的脑子排不出来,你就把他们当作从小到大的顺序吧)
好了,至此,一个倒排索引就创建好了,由两部分组成,我实现的时候就是这么实现的,一个结构用B+树存储字典,另一个就是一个顺序的文件,B+树的叶子节点存一个指向倒排文件的文件偏移量,固然,你也能够用前面的哈希表或者跳跃表,甚至还有其余类型的树,好比trie树来实现,或者你还有其余新的高效数据结构也行。
####咱们再来讲说B+树,为何选它?
以前我实现的时候用的是哈希表,并且大部分的搜索引擎用的都是哈希表,为何用树呢
最后说说我实现的这棵B+树,首先,为了更少的占用内存,我是用的磁盘的形式实现的,而且用了mmap的方式来加快读写速度,没有用双向指针,而用的栈来记录查询的路径,速度还行吧,构造一棵10万个随机字符串的树大约须要3秒,随机查询10万次大约须要150毫秒,每次1.5微秒。
固然,我实现的时候比较仓促,就是按照算法硬编码快速撸出来的,因此我这个B+树还有很是大的优化空间,首先,个人key如今是肯定的,不能超过64字节,而且每一个节点最多100个元素,当时为了快,肯定的key和元素个数比较好编程,若是变成动态的更加节省空间,其次,没有特别的考虑连续key的状况,连续key的插入会形成空间浪费一半,还有,把速度问题交给了mmap来解决,若是内存足够,实际上启动的时候预读取非叶子节点到内存的话,查询起来会更快,不过目前基本上知足需求了,你们若是对B+树实现很感兴趣,能够看看bolt这个项目,这个是一个B+树实现的KVDB,并且是带事务的哦。
若是你以为不错,欢迎转发给更多人看到,也欢迎关注个人公众号,主要聊聊搜索,推荐,广告技术,还有瞎扯。。文章会在这里首先发出来:)扫描或者搜索微信号XJJ267或者搜索西加加语言就行