MongoDB索引问题

索引类型:mysql

MongoDB有多种索引类型,每种索引类型有其适合的场景。sql

  1. 单字段索引
  2. 复合索引
  3. 多key索引
  4. 文本索引
  5. 其余

对于单字段索引而言,升序和降序效果是同样的。mongodb

复合索引针对多个字段联合建立索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,以此类推。复合索引也能知足单个字段的索引,但仅限复合索引首个字段。数据库

当索引的字段为数组时,建立出的索引为多key索引,多key索引会为数组的每一个元素创建一条索引,好比下图所示BillInterceptLifeInfo表中加入一个NeedSyncSiteCodes字段,须要查询NeedSyncSiteCodes中是否包含了某个sitecode就能够利用该字段的多key索引。json

 

实际场景:api

拦截件监控代码中,主要的数据在一个拦截件生命期表, 该表记录了拦截件的生命期状态,一个应下发设备表和一个实际下发设备表。数组

表结构以下:性能

其中更新应下发设备表是要查询出1.站点信息相符的全部单号,且该单号的2.结束时间大于当前时间,且该3.应下发List中不含即将插入的deviceID才会插入一条记录。优化

由于须要下发的站点列表和须要下发的设备列表是两个list,没法一块儿建索引,所以决定建EndTime和NeedSyncSiteCodes的复合索引,NeedSyncSiteCodes也是一个多key索引。url

一开始建索引以下:

 

 db.BillInterceptLifeInfo.createIndex({  "EndTime" : 1, "NeedSyncSiteCodes" : 1 }) 
代码上线后,一开始平稳,但数据量上千后开始不稳定
后根据系统优化提示将索引改成:
 db.BillInterceptLifeInfo.createIndex({ "NeedSyncSiteCodes" : 1 , "EndTime" : 1,}) 
监控如图:
根据某两条查询对比来看:
前:  后:
能够看出,组合索引的前后顺序不一样,EndTime在前的索引Key match到的记录有5K多条,而实际须要修改的只有3条,
NeedSyncSiteCodes在前的索引Key match到的记录有107条,而这107条都是须要修改的,NeedSyncSiteCodes在前的这条索引能缩小二次匹配的范围程度更大。
在复合索引中,多个字段应把最有区分度的字段放前面,好比一个person表中有一个[name + age]的复合索引,age字段的取值颇有限,即拥有相同age字段的文档会有不少;而name字段的取值则丰富不少,拥有相同name字段的文档不多;显然先按name字段查找,再在相同name的文档里查找age字段更为高效。
同理,在此例子中的EndTime和NeedSyncSiteCodes两个字段建复合索引,EndTime的区分度确定不如NeedSyncSiteCodes的多key索引。所以将NeedSyncSiteCodes做为复合索引的第一项更高效。
 
复合多key索引中:
  • 对于一个复合多key索引,每个索引最多能够包含一个数组。
  • 在多于一个数组的情形下来建立复合多key索引不被支持。

 

另外谈下B树(即B-树)和B+树的区别,以及为何mongodb用B-树而不用B+树。

首先B树结构(细节请自行查阅)以下图:

每一个节点存有key对应的data, 每一个节点上的n个key有n+1个子节点。

一个m阶的B树每一个节点至少有m个孩子。

一棵含有N个总关键字数的m阶的B树的最大高度是log_ceil(m/2)(N+1)/2 + 1。

所以B数的高度相对会降低,而高度降低,定位数据会更快。因为B数节点中存数据,最快查询可为O(1)。

 

而B+树,以下图:

 

B+树的特色是,key的副本存储在内部节点,真正的key-data存储在叶子节点上。

n个key的节点指针域是n而不是n+1(mongodb 是n+1)

为了增长区间访问性,B+树的叶子节点两两相连,对于范围查询大大增长了友好度。

 

B树和B+树在磁盘访问这一点上

  1. B树由于key对应的data直接在节点上,所以查询到能够直接取出,最好的状况下查询很是快,且磁盘访问会降低。可是正由于如此,单个节点存储太大,若是没有访问到key,再要往下查询时,须要读入内存的数据量就很大。
  2. B+树由于内部节点只存key的副本,所以查询效率相对很稳定。但也是由于存储了key的副本,致使整个索引相对会比较大。

 

B树和B+树各有优缺点,对于mongodb来讲,mongdb是一种文档型数据库,使用json格式保存数据,归属于聚合型数据库。适用于数据模型简单,性能要求高的场合。

而mysql之类的关系型数据库,区间访问是很常见的现象,B+树支持区间访问,所以mysql更适合用B+树。

相关文章
相关标签/搜索