为什么mongodb使用b树

一,b树

因为我们要考虑磁盘IO的影响,它相对于内存来说是很慢的。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。所以我们要减少IO次数,对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,它的每个节点最多包含m个孩子,m称为b树的阶,m的大小取决于磁盘页的大小。

一个M阶的b树具有如下几个特征:

定义任意非叶子结点最多只有M个儿子,且M>2;

根结点的儿子数为[2, M];

除根结点以外的非叶子结点的儿子数为[M/2, M],向上取整;

非叶子结点的关键字个数=儿子数-1;

所有叶子结点位于同一层;

k个关键字把节点拆成k+1段,分别指向k+1个儿子,同时满足查找树的大小关系。

有关b树的一些特性,注意与后面的b+树区分:

关键字集合分布在整颗树中;

任何一个关键字出现且只出现在一个结点中;

搜索有可能在非叶子结点结束;

其搜索性能等价于在关键字全集内做一次二分查找;

二,b+树

b+树,是b树的一种变体,查询性能更好。m阶的b+树的特征:

有n棵子树的非叶子结点中含有n个关键字(b树是n-1个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b树是每个关键字都保存数据)。

所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。

通常在b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

同一个数字会在不同节点中重复出现,根节点的最大元素就是b+树的最大元素。

b+树相比于b树的查询优势:

b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;

b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢);

对于范围查找来说,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历,

为什么 MongoDB 索引选择B-树,而 Mysql 索引选择B+树

来看下 wiki 百科上 MongoDB 的定义:

MongoDB (from humongous) is a cross-platform document-oriented database. Classified as a NoSQL database, MongoDB eschews the traditional table-based relational database structure in favor of JSON-like documents with dynamic schemas (MongoDB calls the format BSON)

这段话的大致意思是 MongoDB 是文档型的数据库,是一种 nosql,它使用类 Json 格式保存数据。

文档型数据库和我们常见的关系型数据库不同,一般使用 XML 或 Json 格式来保存数据,归属于聚合型数据库。

键值数据库也属于聚合型数据库,熟悉 Redis 的同学应该很好理解。

举个例子:

加入我们要建立一个电子商务网站,类似淘宝这种将商品销售给用户,那么必须存储用户信息、商品目录、订单、收货地址、账单地址、付款方式等。

看下传统的关系型数据库是如何存储的:


 聚合型数据库存储模型:


用类似 Json 的格式表示如下:


相对于 Mysql 关系型数据库,MongoDB 这类 nosql 适用于数据模型简单,性能要求高的场合。

为什么 MongoDB 使用B-树

MongoDB 是一种 nosql,也存储在磁盘上,被设计用在 数据模型简单,性能要求高的场合。性能要求高,看看B/B+树的区别第一点:

B+树内节点不存储数据,所有 data 存储在叶节点导致查询时间复杂度固定为 log n。而B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)

尽可能少的磁盘 IO 是提高性能的有效手段。MongoDB 是聚合型数据库,而 B-树恰好 key 和 data 域聚合在一起。

你可能感兴趣的:(为什么mongodb使用b树)