数据结构--树形结构

来源:互联网 发布:兴城淘宝美工招聘 编辑:程序博客网 时间:2024/05/21 05:07
  • 平衡二叉树

    这里写图片描述

这是个平衡树,一个节点下只有小于两个子叶节点。该树想要达成有效查找,势必需要维持如下一种结构:    树的子叶节点中,左子树一定小于等于当前节点,而当前节点的右子树则一定大于当前节点。只有这样,才能够维持全局有序,才能够进行查询。    这也就决定了只有取得某一个子叶节点后,才能够根据这个节点知道他的子树的具体的值情况。这点非常之重要,因为二叉平衡树,只有两个子叶节点,所以如果想找到某个数据,他必须重复更多次“拿到一个节点的两个子节点,判断大小,再从其中一个子节点取出他的两个子节点,判断大小。”这一过程。    这个过程重复的次数,就是**树的高度**。那么既然每个子树只有两个节点,那么N个数据的树的高度也就很容易可以算出了。树的存储结构:    顺序存储结构:类似数组形式(查询快,插入慢)    链式存储结构:类似链表形式(查询的时候需要大量的寻道时间)优点:    没有空间浪费,不会存在空余的空间,而且查询速度比较快。缺点:    需要取出多个节点,且无法预测下一个节点的位置。这种取出的操作,在内存内进行的时候,速度很快,但如果到磁盘,那么就意味着大量随机寻道。基本磁盘就被查死了。
  • b树
b树:平衡二叉树+顺序存储结构    b树,因为其构建过程中引入了有序数组,从而有效的降低了树的高度,一次取出一个连续的数组,这个操作在磁盘上比取出与数组相同数量的离散数据,要便宜的多。因此磁盘上基本都是b树结构。缺点:    与二叉树相比,他会耗费更多的空间。在最恶劣的情况下,要有几乎是元数据两倍的格子才能装得下整个数据集(当树的所有节点都进行了分裂后)。

b树插入:

这里写图片描述

B树在插入的时候,如果是最后一个node,那么速度非常快,因为是顺序写。

b树更新:

这里写图片描述
但如果有更新插入删除等综合写入,最后因为需要循环利用磁盘块,所以会出现较多的随机io.大量时间消耗在磁盘寻道时间上。

运行时间很长的b树:

这里写图片描述

如果是一个运行时间很长的b树,那么几乎所有的请求,都是随机io。因为磁盘块本身已经不再连续,很难保证可以顺序读取。

如何能够解决这个问题呢?

1: 放弃部分读性能,使用更加面向顺序写的树的结构来提升写性能:
(1),COLA(Cache-Oblivious Look ahead Array)(代表应用自然是tokuDB)。
(2),LSM tree(Log-structured merge Tree)或SSTABLE(代表的数据集是cassandra,hbase,bdb java editon,levelDB etc.)
2:使用ssd,让寻道成为往事。

  • B+树
B+树:平衡二叉树+链式存储结构    b+树在查询过程中应该是不会慢的,但如果数据插入比较无序的时候,比如先插入5 然后10000然后3然后800 这样跨度很大的数据的时候,就需要先“找到这个数据应该被插入的位置”,然后插入数据。这个查找到位置的过程,如果非常离散,那么就意味着每次查找的时候,他的子节点都不在内存中,这时候就必须使用磁盘寻道时间查找。更新基本与插入是相同的。    目前关系型数据库大部分采用该存储结构。
  • LSM树
理解:在内存进行写操作(插入、修改、删除),达到一定阀值之后,持久化到磁盘。    数据首先会插入内存中的树。当内存树的数据量超过设定阈值后,会进行合并操作。合并操作会从左至右便利内存中树的子节点 与 磁盘中树的子节点并进行合并,会用最新更新的数据覆盖旧的数据(或者记录为不同版本)。当被合并合并数据量达到磁盘的存储页大小时。会将合并后的数据(有序的)持久化到磁盘,同时更新父节点对子节点的指针。(类似于定时对磁盘中的数据排序)    读数据:从磁盘中把父节点的数据拿出来,在内存中缓存。    写数据:如果内存中有该节点的数据,则进行直接进行操作。如果不存在则进行读数据。达到一定阀值后持久化到磁盘上。