B树指的是一类树,包括B-树,B+树,B*树等,是一种自平衡的搜索树,它相似普通的平衡二叉树,不一样的一点是B树容许每一个节点有更多的子节点。B树是专门为外部存储器设计的,如磁盘,它对于读取和写入大块数据有良好的性能,因此通常用在文件系统及数据库中。
传统用来搜索的平衡二叉树有不少,AVL树,红黑树等。这些树在通常状况下的查询性能很是好,但当数据量很是大的时候就无能为力了。数据量很是大时,内存不够用,大部分数据只能存放在磁盘上,只有须要的数据才加载到内存。通常而言内存的访问时间为50ns,而磁盘在10ms左右。速度相差了近5个数量级,程序大部分的时间阻塞在磁盘IO上。因此核心就是要减小磁盘IO次数。而像AVL树,红黑树这类平衡二叉树从设计上没法"迎合"磁盘。mysql
上图是一颗简单的平衡二叉树,咱们来看下为何数据库和文件系统用b树而不用平衡二叉树:redis
(1) 它的平衡是经过旋转来实现的,而旋转是对整个树的操做,若部分加载到内存中则没法完成旋转操做。sql
(2) 平衡二叉树的高度比较大(log n), 这样逻辑上很近的节点实际可能很是远,没法很好地利用磁盘预读(空间的局部性原理)数据库
索引的效率实际上依赖于磁盘IO的次数,加快索引的办法就是有效地减小磁盘IO次数。相比于平衡二叉树每次将范围分割为两个区间,B树每次将范围分割成多个区间,区间越多,定位数据越快越精确。多叉下降了B树的高度(底数很大的log n,二叉是底数为2). 那么节点为区间范围,每一个节点就比较大了。所以新建节点时,直接申请页大小的空间(磁盘时按照block分的,通常为512 byte。磁盘IO一次读取若干个block,咱们称为一页,具体大小和操做系统有关,通常为4k,8k或16k),计算机内存分配是按页对齐的,这样一个节点只须要一次IO。那么多叉树的总IO次数也就缩减为log n次。json
上面是一颗B-树,B-树的插入和删除就不具体介绍了,不少资料都描述了这一过程。在普通平衡二叉树中,插入删除后若不知足平衡条件则进行 旋转 操做,而在B-树中,插入删除后不知足条件则进行分裂及合并操做。nosql
咱们来看看B-树的查找,假设每一个节点有 n 个 key值,被分割为 n+1 个区间,注意,每一个 key 值紧跟着 data 域,这说明B-树的 key 和 data 是聚合在一块儿的。通常而言,根节点都在内存中,B-树以每一个节点为一次磁盘 IO,好比上图中,若搜索 key 为 25 节点的 data,首先在根节点进行二分查找(由于 keys 有序,二分最快),判断 key 25 小于 key 50,因此定位到最左侧的节点,此时进行一次磁盘 IO,将该节点从磁盘读入内存,接着继续进行上述过程,直到找到该 key 为止。性能
B+树是B-树的变种,它与B-树的不一样之处在于:mysql索引
由于内节点并不存储 data,因此通常B+树的叶节点和内节点大小不一样,而B-树的每一个节点大小通常是相同的,为一页。优化
为了增长 区间访问性,通常会对B+树作一些优化。
以下图带顺序访问的B+树。网站
B+树节点不存储数据,全部data存储在叶节点致使查询时间负责度固定为log n。而B-树查询时间复杂度不固定,与key在树中的位置有关,最好为O(1)
下面为图示:
B-树
从上图能够看出,key 为 50 的节点就在第一层,B-树只须要一次磁盘 IO 便可完成查找。因此说B-树的查询最好时间复杂度是 O(1)。
B+树
因为B+树全部的 data 域都在根节点,因此查询 key 为 50的节点必须从根节点索引到叶节点,时间复杂度固定为 O(log n)。
B+树叶节点两两相连可大大增长区间访问性,可以使用在范围查询等,而B-树每一个节点key 和data在一块儿,则没法区间查找
B+树能够很好的利用局部性原理,若咱们访问节点 key为 50,则 key 为 5五、60、62 的节点未来也可能被访问,咱们能够利用磁盘预读原理提早将这些数据读入内存,减小了磁盘 IO 的次数。
固然B+树也可以很好的完成范围查询。好比查询 key 值在 50-70 之间的节点。
这个很好理解,因为B-树节点内部每一个 key 都带着 data 域,而B+树节点只存储 key 的副本,真实的 key 和 data 域都在叶子节点存储。前面说过磁盘是分 block 的,一次磁盘 IO 会读取若干个 block,具体和操做系统有关,那么因为磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大。这就意味着B+树单次磁盘 IO 的信息量大于B-树,从这点来看B+树相对B-树磁盘 IO 次数少。
从上图能够看出相同大小的区域,B-树仅有 2 个 key,而B+树有 3 个 key。
mysql是传统的关系型数据库,而MongoDB是文档形的数据库,是一种nosql,它使用xml或json格式来保存数据,归属于聚合型数据库。(键值数据库也属于聚合型数据库,好比redis)
咱们要创建一个电子商务网站,相似淘宝这种将商品销售给用户,那么必须存储用户信息、商品目录、订单、收货地址、帐单地址、付款方式等。
(1)传统的关系型数据库模型
(2)聚合型数据库存储模型
用相似json的格式表示以下:
//Customer { "id":1, "name":Tom, "billingAddress":[{"city":"China"}] } //Orders { "id":99, "orderItem":[ "productId"27, "price":100, "productName":book ], "shippingAddress":[{"city":"china"}], "orderPayment":[ ... ] }
相对于 Mysql 关系型数据库,MongoDB 这类 nosql 适用于数据模型简单,性能要求高的场合
MongoDB 是一种 nosql,也存储在磁盘上,被设计用在 数据模型简单,性能要求高的场合。上面说过,尽可能减小磁盘IO是提升性能的有效手段,而B-树刚好key和data域聚合在一块儿,复杂度最好为O(1)。
(1) Mysql 是一种关系型数据库,区间访问是常见的一种状况,而 B-树并不支持区间访问,而B+树因为数据所有存储在叶子节点,而且经过指针串在一块儿,这样就很容易的进行区间遍历甚至所有遍历
(2) 其次B+树的查询效率更加稳定,数据所有存储在叶子阶段,查询时间复杂度固定为O(log n)。
(3) B+树更适合外部存储,因为内节点无data域,每一个节点能索引的范围更大更精确
摘自: http://blog.csdn.net/wwh578867817/article/details/50493940