我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有
这是mongo第四篇“索引探索”,后续会连续更新4篇

mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流。通过上三篇的介绍,我相信大家对我在使用上已经很溜啦,但是在实际使用中还需要注重效率提升,本文章探索索引,就是为提升效率为出发点,本文的介绍顺序是:索引简介->索引原理->索引类型->索引与查询结合使用->小结,让我们一起来一步一步的探索吧。
01
索引简介
Mongodb的索引和其它关系型数据库索引很类似,索引是一个存储结构,其存储的内容是数据文档持久化的位置信息。一个数据集合和一本书来对比,那么索引就是书对应的目录,其作用就是加快查询效率。索引在加快查询效率的同时,在更新、删除、新增数据时也会影响数据变更效率,因为每一次数据变更都会更新一次索引。所以在索引使用时也需要慎重。
Mongodb索引的基本命令包括:
新增索引:createIndex({字段:排序方式},{可选参数})
删除索引:dropIndex({字段:排序方式})
查看索引:getIndexes()
先不管索引为什么能够提高查询效率,降低数据变更效率,先来一个实例。为了体现效果,这次我整的有点狠,直接初始化了300多万条数据,演示步骤如下:
数据初始化:
for(var i=0;i<3000000 ;i++)
{
db.user.insert({
name:"我叫"+i,
age:i%10,
from:i%10000
})
}
// 上面的数据有一个特点age的值就10个,from的值有10000个。下面分别对两个字段加上索引,并通过实际的执行语句来看效果。
给user表的age添加一个索引(age升序)
db.user.createIndex({age:1})
给user表的from添加一个索引(from升序)
db.user.createIndex({from:1})

其实我们都知道索引能够提高查询效率,估计很少亲自测试一把,通过测试是不是有一种爽歪歪的感觉。根据实际操作结果我们先得出几点小小的结论:
- 当字段的值是有限的一些值时,其实有无索引对效率无影响;
- 当字段的值重复数据少时,索引的查询效率明显提高几百倍;
- 当查询结果需要排序时,有索引比没索引的效率高50倍左右;
- 当更新时,有索引的效率低于无索引;
- 所以在添加索引时针对字段值是有限的值时,就没必要添加索引,当经常需要用于排序的字段可以考虑添加索引。
以上的几个结论,也是我通过实际数据操作得出的,如果有不准确的地方,希望指点改正,谢谢!
先把结论得到这儿,下面我们在一步一步的剖析索引。
02
索引原理
Mongdb数据通过存储引擎持久化以后,其实在磁盘中就是一个一个的文件,每一个文件都对应一个位置信息。索引就是这一些文件位置信息与索引字段值的对应关系的有序数据集合,索引采用btree的结构持久化存储。在创建索引后,数据在查询的时,直接索引数据集合查询,然后在根据对于的位置信息操作对应的数据详情,避免了全表扫描,同时查询出的数据本来就是有序的数据,也避免了因为排序导致的性能损失。
这样我们就不难理解上面得出的几点结论了:因为索引查询避免了全表数据扫描,所有查询效率高;因为索引本身就已经是有序的数据,所以根据索引字段排序效率明显提高;因为索引会单击存储,一旦数据有变更,都需要同时更新索引数据,所有数据更新时有索引的效率低,同时索引也会增加额外的存储开销。
03
索引类型
MongoDB支持多种类型的索引,包括单字段索引、复合索引、多key索引、文本索引等,每种类型的索引有不同的使用场合。
单字段索引:
单字段索引其实很好理解,文章开始我们创建的实例就是单字段索引,简单的所说就是针对某一个字段创建一个索引,达到提高索引字段的查询效率。Mongdb默认_id字段创建单字段唯一索引。
格式:db.collectionName.createIndex({索引字段:1升序-1降序} )
实例:对集合user的字段age添加升序索引
db.user.createIndex({age:1})
复合索引:
复合索引是针对单字段索引的升级版,复合索引就是联合多个字段创建索引,也是我们常说的联合索引。复合索引在数据存储上,首先根据第一字段排序、然后当第一字段值相同时在以第二字段排序、依次类推第N字段。复合索引能够满足以下两个场景的查询需要:根据复合索引多个字段组合查询;根据所有前缀字段查询,也就是所有字段的顺序的第一个至第N个的前缀字段查询。
格式:db.collectionName.createIndex({索引字段1:排序, 索引字段2:排序} )
实例:对集合user添加字段from降序、age升序索引
db.user.createIndex({from:-1,age:1 })
以下情况可以使用到索引:
db.user.find({from:20,age:8})、db.user.find({from:20})
以下情况不能使用索引:
db.user.find({age:8,from:20})、db.user.find({age:8})
根据复合索引的使用情况得出以下几点小结论:
- 索引使用顺序一定要和索引创建顺序保持一致;
- 当索引字段不完全组合查询时,需要前序字段连续;
- 创建索引时最好取值丰富的字段在前。
多key索引:
多key索引是指创建的索引字段为数组,多key索引会为数组的每个元素建立一条索引,使用场景就是针对字段值是数组的查询。有了前面的基础,这一个就很好理解,就不在详细描述了。
文本索引:
文本索引,简单的说就是针对文本数据创建索引,比如,文章信息表,如果需要根据文章关键词检索,那么就可以对文章字段创建文本索引。格式为:db.collectionName.createIndex({索引字段1: "text" } )
04
索引额外属性说明
createIndex创建索引时,该方法有两个参数,第一个参数就是索引字段,上面已经说了,第二个参数就是索引的额外属性,下面我们就说说索引额外属性信息。索引额外属性包括:唯一索引、TTL索引、稀疏索引。
TTL索引:
TTL索引属性是修饰当文档存储自定时间,当超出指定时间后,数据被被自动删除,使用场景为数据只存储指定时间,如:日志数据,关键词为expireAfterSecs,格式为:db.collectionName.createIndex({索引字段1: "text" }, {"expireAfterSecs": 失效时间单位为秒})。
TTL索引几点注意事项:
- TTL只使用于时间字段
- TTL不使用于联合索引
- TTL如果对于索引值是数组,那么只要其中一个值满足要求就自动删除
唯一索引 (unique index):
保证索引对应的字段不会出现相同的值,比如_id索引就是唯一索引。格式为:db.collectionName.createIndex({索引字段1: "text" }, {"unique": true})。
部分索引 (partial index):
只针对符合某个特定条件的文档建立索引,3.2版本才支持该特性。关键词为partialFilterExpression,
格式为:db.collectionName.createIndex({索引字段1: "text" }, {"partialFilterExpression": {数据满足条件表达式}})。
比如:对表user只有age=9的数据创建索引
db.user.createIndex({age:1},
{"partialFilterExpression":{age:9}})
稀疏索引(sparse index):
只针对存在索引字段的文档建立索引,可看做是部分索引的一种特殊情况。关键词为:sparse,格式为:db.collectionName.createIndex({索引字段1: "text" }, {"sparse": true})。
06
索引优化(profiling)
其实我们在建集合的时候,很多时候最开始是不知道那一些字段需要添加索引,是需要根据后续的实际使用场景来动态创建,那么这就会有一个问题,如果监控哪一些字段需要添加或是删除索引,可通过检测每一次操作结果的响应时间长短来动态创建索引,mongdb提供了一个profiling来动态检测执行响应情况。
MongoDB支持对DB的请求进行profiling,目前支持3种级别的profiling。
- 0: 不开启profiling
- 1: 将处理时间超过某个阈值(默认100ms)的请求都记录到DB下的system.profile集合 (类似于mysql、redis的slowlog)
- 2: 将所有的请求都记录到DB下的system.profile集合(生产环境慎用)
通常,生产环境建议使用1级别的profiling,并根据自身需求配置合理的阈值,用于监测慢请求的情况,并及时的做索引优化。
开启profiling命令:db.setProfilingLevel(1,120 );
查询profil记录信息:db.system.profile.find()
最终通过查询出来的记录信息,对索引进行优化。
07
小结
Mongdb在提升查询效率上是很有帮助,但是在实际使用中也不要滥用,否则会适得其反,下面总结几点,供参考:
- 索引创建时最好作用于取值丰富的字段,有限值的字段就没必要添加索引;
- 经常排序的字段,可以考虑添加索引;
- 一个集合中索引的个数不是越多越好,需要根据实际情况来定;
- 执行接口慢,有可能是缺少索引(查询慢),也有可能是索引使用不当(编辑慢);
- 复合索引在使用时,一定要结合索引字段的顺序使用。
我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有的更多相关文章
- 我叫Mongo,干了「查询终结篇」,值得您拥有
这是mongo第三篇"查终结篇",后续会连续更新5篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流. 通 ...
- 我叫Mongo,收了「查询基础篇」,值得你拥有
这是mongo第二篇「查询基础篇」,后续会连续更新6篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流. 通过上一篇基础篇的介 ...
- 「 MySQL高级篇 」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- 「MySQL高级篇」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- 「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景
大家好,我是melo,一名大三后台练习生 专栏回顾 索引的原理&&设计原则 欢迎关注本专栏:MySQL高级篇 本篇速览 在我们上一篇文章中,讲到了索引的原理&&设计原则 ...
- 「MySQL高级篇」MySQL锁机制 && 事务
大家好,我是melo,一名大三后台练习生,最近赶在春招前整理整理发过的博客~! 引言 锁锁锁,到哪到离不开这桩琐事,并发琐事,redis琐事,如今是MySQL琐事,这其中琐事,还跟MySQL另一个重要 ...
- 「MySQL高级篇」MySQL之MVCC实现原理&&事务隔离级别的实现
大家好,我是melo,一名大三后台练习生,死去的MVCC突然开始拷打我! 引言 MVCC,非常顺口的一个词,翻译起来却不是特别顺口:多版本并发控制. 其中多版本是指什么呢?一条记录的多个版本. 并发控 ...
- AS技巧合集「调试技巧篇」
转载:http://www.apkbus.com/forum.php?mod=viewthread&tid=254726&extra=page%3D2%26filter%3Dautho ...
- AS技巧合集「编码技巧篇」
转载:http://www.apkbus.com/forum.php?mod=viewthread&tid=254725&extra=page%3D2%26filter%3Dautho ...
随机推荐
- SMB远程代码执行漏洞(CVE-2020-0796)分析、验证及加固
这几天有点忙,CVE-2020-0796出来了,没静下心来关注一下,显得太不尊重这个漏洞了,今天周末,关注一下,水一篇. 一.漏洞描述 漏洞公告显示,SMB 3.1.1协议 ...
- Docker学习第一天(Docker入门&&Docker镜像管理)
简介 今天小区的超市买零食老板给我说再过几天可能就卖完了我有点诧异,老板又说厂家不生产了emmm 今天总算开始docker了! 1.Docker? 1.什么是Docker Docker 是一个开源的应 ...
- 他凭借这70份PDF,3170页文件,成功斩获了含BATJ所有的offer
前言 最近我一直在面试高级工程师,不管初级,高级,程序员,我想面试前,大家刷题一定是是少不了吧. 我也一样,我在网上找了很多面试题来看,最近又赶上跳槽的高峰期,好多粉丝,都问我要有没有最新面试题,索性 ...
- 金九银十已到!Cookie 和 Session的这些知识你必须知道,面试必问!
前言 会话:一次会话中包含多次请求和响应 注:一次会话表示浏览器第一次给服务器发送请求,会话建立,直到有一方断开为止 功能:在一次会话的多次请求间共享数据 方式: (1) 客户端会话技术:Cookie ...
- window安装elasticsearch和kibana
本次测试安装5.1.1版本 es下载地址:https://www.elastic.co/downloads/past-releases/elasticsearch-5-1-1 选择zip kibana ...
- [LGOJ1273]有线电视网
solution 用了一个很有意思的转移方法. $dp[i][j] $ 表达 \(i\) 作为根,\(j\)个终端时最大的收益,即钱数,当\(0\leq dp[1][i]\)时,即以1为根可以转移到\ ...
- 【P1588】丢失的牛——区间dp/bfs
(题面来自Luogu) 题目描述 FJ丢失了他的一头牛,他决定追回他的牛.已知FJ和牛在一条直线上,初始位置分别为x和y,假定牛在原地不动.FJ的行走方式很特别:他每一次可以前进一步.后退一步或者直接 ...
- CentOS6.5配置KVM
///确认cpu是否支持kvm egrep '(vmx|svm)' --color=always /proc/cpuinfo ///安装包 yum -y install qemu-kvm libvir ...
- MongoDB去重
db.集合.aggregate([ { $group: { _id: {字段1: '$字段1',字段2: '$字段2'},count: {$sum: 1},dups: {$addToSet: '$_i ...
- 从七牛云迁移图片到github
迁移理由 问题是网站的大部分图床都是用的七牛云,官网有改动,所以原测试域名都失效,所以决定进行迁移,将七牛云中的图片迁移到github仓库中. 迁移步骤 Step1:从废弃测试域名空间至可用测试域名空 ...