MongoDB 单字段索引和复合索引
2016-12-25 16:33
357 查看
MongoDB中常见的索引有单字段索引和复合索引.
通常索引应该建立在常用的查询的字段上, 对于不常用的字段不应该建立索引.
在以下的例子中, 由于集合中数据量比较大, 直接排序会超过MongoDB对单次操作的内存限制32M. 所以我们在以下的操作使用的users集合数据量为10W.
上面的例子中先对age进行排序, 然后再对username排序.我们已经对username建立了索引, 但是这个查询并不能使用到username索引.
查询其explain信息
发现其内存使用了98K, 扫描了所有的10W条文档, 耗时124ms.
再次进行上面的查询和explain信息. 返回1000个文档, 也只扫描了1000个文档, 耗时1ms. 之前的索引没有使用时, 扫描了所有文档, 耗时124ms.
要点:
查询索引:
db.users10W.getIndexes()
建立索引:
简单索引: db.users.ensureIndex({“username”: 1})
复合索引: db.users10W.ensureIndex({“age”: 1,”username”: 1})
删除索引
db.users10W.dropIndex(“username_1”)
单字段索引
没有索引的查询
>db.users.find({username:"user0115"}).explain(true) //以下是其中的一部分, 可以看到docsExamined为100W,即扫描了所有的文档, 查询时间为executionTimeMillis为318ms //db.users.find({username:"user123456"}).explain(true).executionStats.executionTimeMillis 可以直接查看花费的时间 "executionStats" : { ..... "executionSuccess" : true, "executionTimeMillis" : 318, "nReturned" : 1, "totalDocsExamined" : 1000000, "totalKeysExamined" : 0 ..... }
建立索引
这次我们对username新建一个索引, 1表示增序排列:>db.users.ensureIndex({"username":1})
索引分析
db.users.find({username:"user0115"}).explain(true) //返回如下, 其中indexName表示使用到了这个索引, executionTimeMillis为0ms,totalDocsExamined为1, 只扫描了1个文档, 改变非常的大 .... "indexName" : "username_1", "indexVersion" : 1, "invalidates" : 0, "isEOF" : 1, "isMultiKey" : false, "isPartial" : false, "isSparse" : false, "isUnique" : false, "keyPattern" : { "username" : 1 } ...... "executionSuccess" : true, "executionTimeMillis" : 0, "nReturned" : 1, "totalDocsExamined" : 1, "totalKeysExamined" : 1 .....
注意事项
新建索引后, 每次写操作(插入, 更新, 删除)文档都要更新索引. MongoDB限制每个集合上最多只能有64个索引. 通常在一个特定的集合上, 不应该拥有两个以上的索引.通常索引应该建立在常用的查询的字段上, 对于不常用的字段不应该建立索引.
复合索引
索引所对应的值是按一定顺序排列的,因此使用索引对文档进行排序非常快.然而进行排序时, 只能使用到一个索引, 我们需要把希望使用的索引放到第一个位置.在以下的例子中, 由于集合中数据量比较大, 直接排序会超过MongoDB对单次操作的内存限制32M. 所以我们在以下的操作使用的users集合数据量为10W.
>db.users10W.find().sort({"age": 1 , "username" : 1}).limit(1000)
上面的例子中先对age进行排序, 然后再对username排序.我们已经对username建立了索引, 但是这个查询并不能使用到username索引.
查询其explain信息
..... "memLimit" : 33554432, "memUsage" : 98341, ..... "executionSuccess" : true, "executionTimeMillis" : 124, "nReturned" : 1000, "totalDocsExamined" : 100000, "totalKeysExamined" : 0 .....
发现其内存使用了98K, 扫描了所有的10W条文档, 耗时124ms.
建立复合索引
如果这个查询比较普遍的话, 可以在对这两个字段一起建立索引, 称为复合索引(compound index). 如果查询中有多个排序或者查询条件中有多个键, 这个索引就会很有用.>db.users10W.ensureIndex({"age":1,"username":1}) >db.users10W.getIndexes() { "key" : { "_id" : NumberInt("1") }, "name" : "_id_", "ns" : "test.users10W", "v" : NumberInt("1") }, { "key" : { "username" : 1 }, "name" : "username_1", "ns" : "test.users10W", "v" : NumberInt("1") }, { "key" : { "age" : 1, "username" : 1 }, "name" : "age_1_username_1", "ns" : "test.users10W", "v" : NumberInt("1") }
复合索引分析
可以看到第3个是刚刚新加的复合索引.再次进行上面的查询和explain信息. 返回1000个文档, 也只扫描了1000个文档, 耗时1ms. 之前的索引没有使用时, 扫描了所有文档, 耗时124ms.
... "executionSuccess" : true, "executionTimeMillis" : 1, "nReturned" : 1000, "totalDocsExamined" : 1000, "totalKeysExamined" : 1000 ..... "indexName" : "age_1_username_1", "indexVersion" : 1, "isMultiKey" : false, "isPartial" : false, "isSparse" : false, "isUnique" : false, "keyPattern" : { "age" : 1, "username" : 1 }, ....
结论
不管是简单索引还是复合索引. 在使用正确的情况下, 都大大加快了查询速度.语句 | 集合大小 | 索引情况 | 花费时间 | 扫描文档数 |
---|---|---|---|---|
db.users.find({username:”user0115”}) | 1M | 无 | 318ms | 1M |
db.users.find({username:”user0115”}) | 1M | db.users.ensureIndex({“username”:1}) | 0ms | 1 |
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000) | 0.1M | 无 | 124ms | 0.1M |
db.users10W.find().sort({“age”: 1 , “username” : 1}).limit(1000) | 0.1M | db.users10W.ensureIndex({“age”:1,”username”:1}) | 1ms | 1000 |
查询索引:
db.users10W.getIndexes()
建立索引:
简单索引: db.users.ensureIndex({“username”: 1})
复合索引: db.users10W.ensureIndex({“age”: 1,”username”: 1})
删除索引
db.users10W.dropIndex(“username_1”)
相关文章推荐
- MongoDB查询字段没有创建索引导致的连接超时异常解案例分享
- MongoDB查询字段没有创建索引导致的连接超时异常解案例分享
- Mongodb在查询某个字段是否存在,执行删除字段,python中排序和创建索引
- spring-data-mongodb的同字段索引多条件查询
- 在使用mongoDB 中Group时,分组字段不是唯一索引记录数不能大于2000
- MongoDB数据导出、导入及索引建立
- Order by 字段加在索引何处
- Mongodb 稀疏索引 sparse
- MongoDB大表建索引,出现一些问题
- mongodb处理中文索引和查找字符串
- Mongodb 字段类型转换
- mongodb 索引相关
- MongoDB笔记三:C Driver 含日期类型字段document添加和查询,指定document返回的field
- MySQL脚本添加字段和修改字段/索引的方法
- MongoDb中修改记录的指定字段
- Mongodb-索引
- Sql Server之旅——第七站 为什么都说状态少的字段不能建索引
- Mongodb 3.2 Java 显示指定字段 条件查询 官方
- Mongodb源码分析--插入记录及索引B树构建
- mongodb-条件操作符、排序、索引、聚合