https://blog.csdn.net/congcong68/article/details/46955115
一、简介
在MongoDB建立索引能提高查询效率,只需要扫描索引只存储的这个集合的一小部分,并只把这小部分加载到内存中,效率大大的提高,如果没有建立索引,在查询时,MongoDB必须执行全表扫描,在数据量大时,效率差别就很明显,对于包括一个没有索引的排序操作的查询,服务器必须在返回任何结果之前将所有的文档加载到内存中来进行排序。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。索引项的排序支持高效的相等匹配和基于范围的查询操作。
从mongoDB 3.0开始ensureIndex被废弃,使用 createIndex创建索引。
db.collection.createIndex(keys,options)
参数 | 类型 | 描述 |
keys | document | 一个包含该字段的字段和值对的文档,该文档的索引键和该值描述该字段的索引类型。对于某个领域的上升索引,指定一个值为1;对于下降的索引,指定一个值为1。 MongoDB支持几种不同的索引类型,包括文本,空间,和哈希索引。查看更多信息的索引类型。 |
options | document | 在创建索引的时的限 |
1. 默认索引
存储在MongoDB集合中的每个文档(document)都有一个默认的主键“_id“,如果我们在添加新的文档时,没有指定“_id“值时,MongoDB会创建一个ObjectId值,并创建会自动创建一个索引在“_id“键上,默认索引的名称是”_id_“,并无法删除
2. 查看索引信息
返回一个数组,该数组保存标识和描述集合上现有索引的文档列表,可以查看我们是否有对某个集合创建索引,并创建哪些索引,方便我们管理。
db.collection.getIndexes()
3. 创建单列索引
我们对文档单个字段创建索引或者对内嵌文档的单个字段创建索引
语法:
db.collection.createIndex({field:boolean} })
boolean:对于某个领域的上升索引,指定一个值为1;对于下降的索引,指定一个值为1。
(1)创建
db.orders.createIndex({cname:1})
我们对orders集合创建了cname索引,默认的索引名称是”cname_1“
根据条件查询文档,并查看查询效率怎么样
db.orders.find({"cname":"zcy100000"}).explain()
我们测试有建索引和没建索引在1000000条文档执行查询的效率怎么样,我们这边先使用explain()函数,下一篇我们介绍
我们这边先介绍几个参数
1) n:当前查询返回的文档数量。
2)millis:当前查询所需时间,毫秒数。
3)indexBounds:当前查询具体使用的索引
对一些比较重要的参数说明:
1) n:当前查询返回的文档数量。
2)millis:当前查询所需时间,毫秒数。
3)indexBounds:当前查询具体使用的索引。
4)nscanned:扫描document的行数。
5)cursor:返回游标类型(BasicCursor和BtreeCursor),我们这边使用BtreeCursor类型。
6)nscannedObjects:被扫描的文档数量。
7)scanAndOrder:是否在内存中排序。
我们结果是相差很大的,有建索引字段,查询效率比较高,在大数据时,差别更明显。
(3)查询和排序组合使用
我们查询集合cname大于zcy100的文档并对onumber进行降序排序
db.orders.find({"cname":{$gt:"zcy1000"}}).sort({"onumber":1}).explain()
执行出现错误:
"$err" : "Runner error:Overflow sort stage buffered data usage of 33554456 bytes exceeds internal limit of 33554432 bytes",
我们的内存只有33554432字节,对于包括一个没有索引的排序操作的查询,服务器必须在返回任何结果之前将所有的文档加载到内存中来进行排序。
我们对onumber创建索引
db.orders.createIndex({onumber:-1})
这次我们在执行时,可以正常执行,已经减少了内存的缓存的数据
4. 创建组合索引
我们可以同时对多个键创建组合索引
语法:
db.collection.createIndex({field1:boolean, field2:boolean } })
说明:
db.collection.createIndex({a:1,b:1,c:1 } })
我们对a、b、c进组合创建索引,支持查询时会用到索引的几种:
1) a
2) a,b
3) a,b,c
这三中的查询条件,会使用到索引(1) 创建组合索引
我们同时对onumber和cname进行组合索引
db.orders.createIndex({cname:1,onumber:-1})
5. 内嵌文档的索引
我们对内嵌文档创建索引时,跟基本文档创建索引一样
- db.collection.createIndex({field:boolean} })
(2) 组合的内嵌文档的索引的创建
我们对内嵌文档创建组合索引时,跟基本文档创建组合索引一样
>db.collection.createIndex({field1:boolean, field2:boolean } })
db.orders.createIndex({"items.info":1, "items. quantity":-1})
6. 文本索引
MongoDB提供 text indexes 支持在字符串内容上的文本检索查询。 text 索引可以包括任何值为字符串或者字符串元素数组的字段。
为了执行文本检索查询,您必须在集合上有一个 text 索引。一个集合只能拥有 ** 一个 ** 文本检索索引,但是这个索引可以覆盖多个字段。
db.stores.createIndex( { name: "text", description: "text" } )
$text 操作
使用 $text 查询操作符在一个有 text index 的集合上执行文本检索。
$text 将会使用空格和标点符号作为分隔符对检索字符串进行分词, 并且对检索字符串中所有的分词结果进行一个逻辑上的 OR 操作。
例如,您可以使用下面的查询语句来找到所有包含 “coffee”, “shop”, 以及 “java” 列表中任何词语的商店:
db.stores.find( { $text: { $search: "java coffee shop" } } )
创建文本索引:
考虑下文字后其标签的帖子集合,包含以下文件:
{
"post_text": "enjoy the mongodb articles on yiibai", "tags": [ "mongodb", "yiibai" ] }
我们将创建post_text字段的文本索引,以便我们能够在我们的帖子中搜索文本:
>db.posts.ensureIndex({post_text:"text"})
使用文本索引:
现在,我们已经创建文本post_text字段的索引,我们将搜索所有含有 yiibai.com 一词的帖子。
>db.posts.find({$text:{$search:"yiibai.com"}})
上面的命令返回在文本中含有yiibai单词的帖子,如以下结果文档:
{ "_id" : ObjectId("53493d14d852429c10000002"), "post_text" : "enjoy the mongodb articles on yiibai.com", "tags" : [ "mongodb", "yiibai.com" ] } { "_id" : ObjectId("53493d1fd852429c10000003"), "post_text" : "writing tutorials on mongodb", "tags" : [ "mongodb", "tutorial" ] }
7. 删除索引
我们对已经创建的索引进行删除,可以针对具体的集合中索引进行删除,也可以对所有的集合中的所有索引删除
(1)具体索引名称删除索引
db.collection.dropIndex(index)
删除具体的索引,根据索引名称删除,如果不知道索引的名称,可以通过db.collection.getIndexes()查看索引名称
(2)删除集合中所有索引
db.collection.dropIndexes()
我们对集合中的索引都删除,我们删除cname字段的索引和onumber字段索引,现在只剩默认的_id字段索引,索引我们在使用时,要谨慎,以免把集合中的索引都删除。
总结:
在MongoDB建立索引能提高查询效率,但在MongoDB新增、修改效率上比较慢