MongoDB索引问题
索引类型:
MongoDB有多种索引类型,每种索引类型有其适合的场景。
- 单字段索引
- 复合索引
- 多key索引
- 文本索引
- 其他
对于单字段索引而言,升序和降序效果是一样的。
复合索引针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,以此类推。复合索引也能满足单个字段的索引,但仅限复合索引首个字段。
当索引的字段为数组时,创建出的索引为多key索引,多key索引会为数组的每个元素建立一条索引,比如下图所示BillInterceptLifeInfo表中加入一个NeedSyncSiteCodes字段,需要查询NeedSyncSiteCodes中是否包含了某个sitecode就可以利用该字段的多key索引。
实际场景:
拦截件监控代码中,主要的数据在一个拦截件生命期表, 该表记录了拦截件的生命期状态,一个应下发设备表和一个实际下发设备表。
表结构如下:
其中更新应下发设备表是要查询出1.站点信息相符的所有单号,且该单号的2.结束时间大于当前时间,且该3.应下发List中不含即将插入的deviceID才会插入一条记录。
因为需要下发的站点列表和需要下发的设备列表是两个list,无法一起建索引,因此决定建EndTime和NeedSyncSiteCodes的复合索引,NeedSyncSiteCodes也是一个多key索引。
一开始建索引如下:
![Qian Jiali > MongoDB索引问题 > 监控图.png](http://wiki.rd.800best.com/download/attachments/30998016/%E7%9B%91%E6%8E%A7%E5%9B%BE.png?version=1&modificationDate=1522034403000&api=v2)
![Qian Jiali > MongoDB索引问题 > EndTime_1_NeedSyncSiteCodes_1.jpg](http://wiki.rd.800best.com/download/attachments/30998016/EndTime_1_NeedSyncSiteCodes_1.jpg?version=1&modificationDate=1522036815000&api=v2)
![Qian Jiali > MongoDB索引问题 > NeedSyncSiteCodes_1_EndTime_1.jpg](http://wiki.rd.800best.com/download/attachments/30998016/NeedSyncSiteCodes_1_EndTime_1.jpg?version=1&modificationDate=1522036717000&api=v2)
- 对于一个复合多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+树在磁盘访问这一点上
- B树因为key对应的data直接在节点上,因此查询到可以直接取出,最好的情况下查询非常快,且磁盘访问会下降。但是正因为如此,单个节点存储太大,如果没有访问到key,再要往下查询时,需要读入内存的数据量就很大。
- B+树因为内部节点只存key的副本,因此查询效率相对很稳定。但也是因为存储了key的副本,导致整个索引相对会比较大。
B树和B+树各有优缺点,对于mongodb来说,mongdb是一种文档型数据库,使用json格式保存数据,归属于聚合型数据库。适用于数据模型简单,性能要求高的场合。
而mysql之类的关系型数据库,区间访问是很常见的现象,B+树支持区间访问,因此mysql更适合用B+树。