在mongodb中,索引可以按字段升序/降序来创建,便于排序,默认是按btree来组织索引文件,也允许建立hash索引:
explain.queryPlanner: queryPlanner的返回
explain.queryPlanner.namespace:该值返回的是该query所查询的表
explain.queryPlanner.indexFilterSet:针对该query是否有indexfilter
explain.queryPlanner.winningPlan:查询优化器针对该query所返回的最优执行计划的详细内容。
explain.queryPlanner.winningPlan.stage:最优执行计划的stage,这里返回是FETCH,可以理解为通过返回的index位置去检索具体的文档。
stage的类型的意义,mongodb的文档中列出了前4种类型,还有一些没有列出来,但是会比较常见,这里一并解释一下。
COLLSCAN :全表扫描
IXSCAN:索引扫描
FETCH::根据索引去检索指定document
SHARD_MERGE:各个分片返回数据进行merge
SORT:表明在内存中进行了排序(与前期版本的scanAndOrder:true一致)
SORT_MERGE:表明在内存中进行了排序后再合并
LIMIT:使用limit限制返回数
SKIP:使用skip进行跳过
IDHACK:针对_id进行查询
SHARDING_FILTER:通过mongos对分片数据进行查询
COUNT:利用db.coll.count()之类进行count运算
COUNTSCAN:count不使用用Index进行count时的stage返回
COUNT_SCAN:count使用了Index进行count时的stage返回
SUBPLA:未使用到索引的$or查询的stage返回
TEXT:使用全文索引进行查询时候的stage返回
queryPlanner返回的结构:
explain.queryPlanner.winningPlan.inputStage:用来描述子stage,并且为其父stage提供文档和索引关键字。
explain.queryPlanner.winningPlan.stage的child stage,此处是IXSCAN,表示进行的是index scanning。
explain.queryPlanner.winningPlan.keyPattern:所扫描的index内容,此处是did:1,status:1,modify_time: -1与scid : 1
explain.queryPlanner.winningPlan.indexName:winning plan所选用的index。
explain.queryPlanner.winningPlan.isMultiKey是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。
explain.queryPlanner.winningPlan.direction:此query的查询顺序,此处是forward,如果用了.sort({modify_time:-1})将显示backward。
explain.queryPlanner.winningPlan.indexBounds:winningplan所扫描的索引范围,如果没有制定范围就是[MaxKey, MinKey],这主要是直接定位到mongodb的chunck中去查找数据,加快数据读取。
explain.queryPlanner.rejectedPlans:其他执行计划(非最优而被查询优化器reject的)的详细返回,其中具体信息与winningPlan的返回中意义相同,故不在此赘述。
executionStats返回结构的意义:
executionStats.executionSuccess:是否执行成功
executionStats.nReturned:满足查询条件的文档个数,即查询的返回条数
executionStats.executionTimeMillis:整体执行时间
executionStats.totalKeysExamined:索引整体扫描的文档个数,和早起版本的nscanned 是一样的
executionStats.totalDocsExamined:document扫描个数, 和早期版本中的nscannedObjects 是一样的
executionStats.executionStages:整个winningPlan执行树的详细信息,一个executionStages包含一个或者多个inputStages
executionStats.executionStages.stage:这里是FETCH去扫描对于documents,后面会专门用来解释大部分查询使用到的各种stage的意思
executionStats.executionStages.nReturned:由于是FETCH,所以这里该值与executionStats.nReturned一致
executionStats.executionStages.docsExamined:与executionStats.totalDocsExamined一致executionStats.inputStage中的与上述理解方式相同
explain.executionStats.executionStages.works:被查询执行阶段所操作的“工作单元(work units)”数。
explain.executionStats.executionStages.advanced:优先返回给父stage的中间结果集中文档个数
explain.executionStats.executionStages.isEOF:查询执行是否已经到了数据流的末尾
这些值的初始值都是0。Works的 值当isEOF为1时要比nReturned大1, isEOF为0是相同。
1.查看执行计划explain
db.stu.find({sn:99}).explain();
(1).未创建索引
(2).增加索引后
db.stu.createIndex({sn:1}) # 1 为升序; 2 为降序
注:新版本创建索引为 db.collection.createIndex() # 1 为升序; -1 为降序
2.查看索引
3.删除单个索引
db.stu.dropIndex({name:-1})
4.删除表下面的所有索引
5.创建多列索引
db.stu.createIndex({sn:1,name:1})
6.子文档索引创建和查询
db.shop.insert({name:'Nokia',spc:{weight:120,area:'*'}});
db.shop.insert({name:'sanxing',spc:{weight:100,area:'hanguo'}});
子文档索引创建
db.shop.createIndex({'spc.area':1})
7.创建唯一索引
db.tea.createIndex({email:1},{unique:true});
创建唯一索引去掉重复的,如下表
在极少数情况下,可能希望直接删除重复的值,创建索引时使用dropDups选项,如果遇到重复值,第一个会被保留,之后重复的文档都会被删除。
dropDups会强制性建立唯一索引,但是这种方式太粗暴了,你无法控制那些文档被保留那些文档被删除(不会提示),对于比较重要的数据,千万不要使用dropDups
db.test7.createIndex({name:1},{unique:true,dropDups:true})
8.创建稀疏索引(null数据将无法查询到)
当使用3.2之后的Mongo版本时,应优先考虑Partial Indexes(部分索引)。
db.tea.createIndex( { "email": 1 }, { sparse: true } );
如果一个稀疏索引会导致一个不完整的结果集查询和排序操作,MongoDB不会使用索引,除非一个hint()显式地指定了索引
db.scores.insert({"userid" : "newbie"})
db.scores.insert({"userid" : "abby", "score" : 82})
db.scores.insert({"userid" : "nina", "score" : 90})
集合在 score 键上有一个稀疏索引
db.scores.createIndex( { score: 1 } , { sparse: true } )
由于userid为 "newbie" 的文档不包含 score 键, 因此稀疏索引中不包含该文档的索引项
假设有如下查询,返回 scores 集合中 所有 文档并按照 score 键排序:
即使是按照被索引键排序,MongoDB仍然 不会 选择稀疏索引来匹配这个查询
db.scores.find().sort( { score: -1 } )
如果希望使用稀疏索引,请在 hint() 显示指定该索引
db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
(稀疏)索引的使用导致了只有那些包含 score 键的文档被返回了
9.hash索引
db.tea.createIndex({email:'hashed'});
10.重建索引
一张表经过很多次修改后,导致表的文件产生碎片,索引文件也是,可以通过索引文件的重建来提高索引的效率
11.向表中插入100w数据
for(i=0;i<1000000;i++){
db.com_user.insert(
{
i:i,
username:'user'+i,
age:Math.floor(Math.random()*120),
created:new Date()
}
)
}
12.创建hash索引
db.collection.createIndex( { _id: "hashed" } )
您可能无法创建一个带有 哈希 索引键的复合索引或者对 哈希 索引施加唯一性的限制。但是,您可以在同一个键上同时创建一个 哈希 索引
和一个递增/递减(例如,非哈希)的索引,这样MongoDB对于范围查询就会自动使用非哈希的索引
警告:MongoDB的 哈希 索引会在哈希前将浮点数字截断为64位整数。例如,如果一个键上存储的值是 2.3, 2.2, 或者 2.9 ,哈希索引存储的哈希值会是一样的。为了避免冲突,请不要对浮点数字使用 哈希 索引,如果这个这个数组无法可靠的转换到64位整数(然后再转换回浮点数字)。MongoDB 哈希 索引不支持大于 253 的浮点数字.
13.创建部分索引
对集合中指定的筛选器表达式筛选后的部分集合进行创建索引,优点:减少了存储空间,提高的查询效率,在3.2版本中,MongoDB现在可以创建部分索引,索引只包含符合给定条件的文档
创建部分索引
db.com_user.createIndex({ name: 1 },{ partialFilterExpression: { age: { $gt: 22 } } } )
查询wangwu数据,不再索引范围内(年龄必须>22才可以走索引)
db.com_user.find({name:'wangwu'}).explain(true).executionStats
搜索年龄>22岁的信息
db.com_user.find({name:'zhangfei',age:50}).explain(true).executionStats