五、MongoDB的索引
五、MongoDB的索引
1、简介
它就像是一本书的目录,如果没有它,我们就需要对整个书籍进行查找来获取需要的结果,即所说的全盘扫描;
而有了目录(索引)之后就可以通过它帮我们定位到目标所在的位置,快速的获取我们想要的结果。
2、演示
第一步,向用户集合users中插入100W条数据
var insertUsers = function() {
var start = new Date().getTime();
for (var i = ; i <= ; i++) {
db.users.insert({
"userid": i,
"username": "wjg" + i,
"age": Math.floor(Math.random() * ), //年龄为0~99的随机整数
"createdate": new Date()
})
}
var end = new Date().getTime();
print("插入100W条数据共耗时" + (end - start) / + "秒");
}
LZ的渣渣I3和4G内存总共耗时了484.623秒,约8分多钟。任务管理器里边可以很清楚的看到当时CPU、内存和磁盘使用率都普遍的增高。
第二步:查询用户名为“wjg465413”的文档对象
db.users.find({username:"wjg465413"}).explain("allPlansExecution")
{
"queryPlanner" : {
"plannerVersion" : ,
"namespace" : "test.users",
"indexFilterSet" : false,
"parsedQuery" : {
"username" : {
"$eq" : "wjg465413"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"username" : {
"$eq" : "wjg465413"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : ,
"executionTimeMillis" : ,
"totalKeysExamined" : ,
"totalDocsExamined" : ,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"username" : {
"$eq" : "wjg465413"
}
},
"nReturned" : ,
"executionTimeMillisEstimate" : ,
"works" : ,
"advanced" : ,
"needTime" : ,
"needFetch" : ,
"saveState" : ,
"restoreState" : ,
"isEOF" : ,
"invalidates" : ,
"direction" : "forward",
"docsExamined" :
},
"allPlansExecution" : [ ]
},
"serverInfo" : {
"host" : "Jack",
"port" : ,
"version" : "3.0.3",
"gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
},
"ok" :
}
说明:这里的explain方法相当于查询计划,它会返回给你查询过程的详细信息。它的参数有三种模式:“queryPlanner”(查询计划[默认])、“executionStats”(执行状态)和“allPlansExecution”(所有执行计划),这里我们只关注它返回给我们的以下几个信息。
"executionTimeMillis" : 865 //执行的毫秒数 注:如果你是第一次执行,可能会花费更长的时间 "totalDocsExamined" : 1000000 //共检查的文档数
第三步:在用户名“username”字段上加上索引
db.users.createIndex({ "username" : })
重新执行上次的查询操作
db.users.find({username:"wjg465413"}).explain("allPlansExecution")
{
"queryPlanner" : {
"plannerVersion" : ,
"namespace" : "test.users",
"indexFilterSet" : false,
"parsedQuery" : {
"username" : {
"$eq" : "wjg465413"
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"username" :
},
"indexName" : "username_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"username" : [
"[\"wjg465413\", \"wjg465413\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : ,
"executionTimeMillis" : ,
"totalKeysExamined" : ,
"totalDocsExamined" : ,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : ,
"executionTimeMillisEstimate" : ,
"works" : ,
"advanced" : ,
"needTime" : ,
"needFetch" : ,
"saveState" : ,
"restoreState" : ,
"isEOF" : ,
"invalidates" : ,
"docsExamined" : ,
"alreadyHasObj" : ,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : ,
"executionTimeMillisEstimate" : ,
"works" : ,
"advanced" : ,
"needTime" : ,
"needFetch" : ,
"saveState" : ,
"restoreState" : ,
"isEOF" : ,
"invalidates" : ,
"keyPattern" : {
"username" :
},
"indexName" : "username_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"username" : [
"[\"wjg465413\", \"wjg465413\"]"
]
},
"keysExamined" : ,
"dupsTested" : ,
"dupsDropped" : ,
"seenInvalidated" : ,
"matchTested" :
}
},
"allPlansExecution" : [ ]
},
"serverInfo" : {
"host" : "Jack",
"port" : ,
"version" : "3.0.3",
"gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
},
"ok" :
}
可以看到两次的查询计划有很大的差别,我们还是着重看下那两个属性值。
"executionTimeMillis" : 53 //执行的毫秒数 "totalDocsExamined" : 1 //共检查的文档数
加过索引之后查询这个文档所耗费的时间仅仅为53毫秒,并且扫描一次直接定位,性能提升了16倍。可见合理使用索引的重要性!
注:“_id”字段是Mongo为我们默认添加的索引,而且是唯一索引,保证了数据的唯一性,不可以移除。另外,使用limit(1)限制查询结果的数量也可以提高查询速度
3、索引的类型
a)、单一索引:可以在数据集上任意一个字段上建立索引,包括普通的属性键、内嵌文档以及内嵌文档中的属性键。
db.users.createIndex({ "username" : }) //普通属性键的索引 //假设class是一个内嵌的文档
db.users.createIndex({ "class" : }) //内嵌文档的索引 db.users.createIndex({ "class.classname" : }) //内嵌文档中的属性键索引
索引方向:1表示升序,-1表示降序
b)、复合索引:以多个属性键为基础而建立得索引
db.users.createIndex({ "username" : , "age" : -, "userid" : }) //在“username”、“age”和“userid”上建立复合索引
索引前缀:通过建立上边的复合索引之后,Mongo就相当于同时拥有了三个索引一样,分别是{"username" : 1},{"username" : 1, "age" : -1}和{"username" : 1, "age" : -1, "userid" : 1},但是像{"age" : -1},{"userid" : 1}或者{"age" : -1, "userid" : 1}这三个索引并不会起作用。所以它会使用包含了前缀(首个)的索引的作为复合索引
c)、多键索引:为数组中的多个值建立索引以实现高效查询。
注:Ⅰ、不允许在多个数组上建立复合索引
Ⅱ、不能指定片键作为多键索引
Ⅲ、哈希索引不能是多键
Ⅳ、多键索引不支持覆盖查询
d)、地理空间索引和查询:Mongo提供了两种曲面类型的索引:2dsphere索引和2d索引。查询类型包括:包含(inclusion),交叉(intersection)和接近(proximity)
e)、文本索引:用来支持查询包含了字符串或者字符串数组的文档
db.users.createIndex({"username" : "text"})
注:文本索引不支持排序并且一个复合文本索引不能再包含其他任何索引了
f)、哈希索引:它可以在使用了哈希片键进行分片的数据集上进行索引,支持相等查询,但是不支持范围查询
db.users.createIndex({"username" : "hashed"})
4、索引特性
a)、TTL(Time-To-Live)索引:是一种具有生命周期的索引,它允许为每一个文档设置一个超时时间
db.users.createIndex({ "createdate" : },{ "expireAfterSecs" : ** })
说明:在“createdate”字段上建立一个TTL索引,当这个自段存在并且是日期类型,当服务器时间比“createdate”字段的时间晚60*60*24秒,即24小时时,文档就会被删除
b)、唯一索引:确保集合的每一个文档的指定键都有唯一值
db.users.createIndex({"username" : }, {"unique" : true})
c)、稀疏索引:Mongo里边的null会被看做值,如果有一个可能存在也可能不存在的字段,我们可以使用稀疏索引
db.users.createIndex({"age" : },{"sparse" : true})
4、索引操作
a)、查看所有索引
db.users.getIndexes()
b)、移除索引
db.users.dropIndex({"createdate1" : })
c)、移除所有索引
db.users.dropIndexes()
d)、重建索引
db.users.reIndex()
说明:该操作会先删除所有索引,包括“_id”,然后重新创建所有索引
五、MongoDB的索引的更多相关文章
- MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引
这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一 ...
- MongoDb进阶实践之七 MongoDB的索引入门
一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...
- 关于mongodb创建索引的一些经验总结(转)
查看语句执行计划: explain() 在mongodb3+版本后输出格式发生改变: 详情参见:https://docs.mongodb.com/v3.0/reference/method/curso ...
- MongoDB的索引(三)
MongoDB的索引: 1. _id索引 该索引是大多数集合默认创建的索引,也就是说用户每插入一个数据,MongoDB会自动生成一条唯一的_id字段. 2. 单键索引 单键索引是最普通的索引,它不会自 ...
- MongoDB 覆盖索引查询
MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...
- MongoDB数据库索引
前面的话 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录.这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查 ...
- MongoDB数据库索引构建情况分析
前面的话 本文将详细介绍MongoDB数据库索引构建情况分析 概述 创建索引可以加快索引相关的查询,但是会增加磁盘空间的消耗,降低写入性能.这时,就需要评判当前索引的构建情况是否合理.有4种方法可以使 ...
- 给MongoDB添加索引
用过数据库的都知道,数据库索引与书籍的索引类似,都是用来帮助快速查找的. MongoDB的索引跟关系型数据库的索引几乎一致. 1. 索引的创建 mongodb采用ensureInd ...
- 分布式系列十五: MongoDB数据库
MongoDB 是基于分布式文件存储的数据库. 开发语言是C++. 具有高性能,可扩展的特点. 是NoSql中最像关系数据库的. 什么是NoSql NoSQL 是 Not only SQL 的缩写. ...
随机推荐
- 修改java在进程中的映像名
java小程序用java -jar xxx.jar 启动的进程映像名都是java.exe. 如果启动多个小程序就不好区分,导致监控程序无法定位到具体需要守护的小程序上. 解决办法: 在java安装目 ...
- 活用RPM获取包的信息
rpm -q 功效大 如果你想要在系统上安装.卸载或是升级软件,需要对系统软件进行查询:或是有如下的场景: 安装了一个软件,需要知道这个软件的版本. 遇到一个文件,不认识它,需要知道它是什么软件,有什 ...
- ADO.NET 基本操作
概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库,类似于PHP中的PDO 使用 连接数据库 (Connection对象) 1. 连接字符串 基本语法:数据源(Data ...
- sys模块的介绍
sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取 ...
- EasyUI自动消失的弹框
$.messager.show( { title : "系统提示", msg : "请选择提供商!!!" });
- Linux磁盘配额
Step1:修改fstab文件,增加磁盘限额用户和用户组信息 # /etc/fstab# Created by anaconda on Sat Dec 29 04:48:18 2018## Acces ...
- 100-days: thirteen
Title: “The Godfather turns 50” <教父>50周年 turn 达到某个年龄 Mario Puzo's(马里奥·普佐) "The Godfather ...
- Object强转为实体类类型失败!!!!!!
这是从我CSDN博客直接拿来的图片废话不多说,直接上代码:
- Python项目--Scrapy框架(二)
本文主要是利用scrapy框架爬取果壳问答中热门问答, 精彩问答的相关信息 环境 win8, python3.7, pycharm 正文 1. 创建scrapy项目文件 在cmd命令行中任意目录下执行 ...
- 获取CNVD的cookie
def getCookie(self): #获取cookie spiderFirefox = webdriver.Firefox() spiderFirefox.get("http://ww ...