本文是一篇转载文章,作者在对MongoDB文档进行了细致的阅读后,总结出了MongoDB的各种索引的用法。
原文链接:http://iamcaihuafeng.blog.sohu.com/151638529.html
索引能提高检索数据的速度,你可以想像成在MySQL中创建索引一样,同样索引也是用B-Tree也实现的。
1.单列索引
在字段x上创建索引,1 (ascending) or -1 (descending)
> db.data.ensureIndex({x:1})
显示表data里面的所有索引
> db.data.getIndexes() [ { "name" : "_id_", "ns" : "recommender.data", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4befb146b0e29ba1ce20e0bb"), "ns" : "recommender.data", "key" : { "x" : 1 }, "name" : "x_1" } ]
查找字段x为6的值,此时已经用到索引了
> db.data.find({x:6}) { "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1" } { "_id" : ObjectId("4bee804ba23d558eb6687118"), "x" : 6, "name" : "caihuafeng2" } { "_id" : ObjectId("4bee804ba23d558eb6687119"), "x" : 6, "name" : "caihuafeng3" } { "_id" : ObjectId("4bee804ba23d558eb668711a"), "x" : 6, "name" : "caihuafeng4" } { "_id" : ObjectId("4bee804ba23d558eb668711b"), "x" : 6, "name" : "caihuafeng5" } { "_id" : ObjectId("4bee804ba23d558eb668711c"), "x" : 6, "name" : "caihuafeng6" } { "_id" : ObjectId("4bee804ba23d558eb668711d"), "x" : 6, "name" : "caihuafeng7" } { "_id" : ObjectId("4bee804ba23d558eb668711e"), "x" : 6, "name" : "caihuafeng8" } { "_id" : ObjectId("4bee804ba23d558eb668711f"), "x" : 6, "name" : "caihuafeng9" } { "_id" : ObjectId("4bee804ba23d558eb6687120"), "x" : 6, "name" : "caihuafeng10" }
2.默认索引
上述1中db.data.getIndexes()显示出来的一共有2个索引,其中_id是创建表的时候自动创建的索引,此索引是不能够删除的。
An index is always created on _id. This index is special and cannot be deleted. The _id index enforces uniqueness for its keys.
3.文档作为索引的键值
a.单列索引
MongoDB的官方文档上面是这样说的:
Documents as Keys
Indexed fields may be of any type, including documents:
往数据库recommender的表data中插入三条记录
> db.data.insert({name:"1616",info:{url:"http://www.1616.net/",city:"beijing"}}); > db.data.insert({name:"hao123",info:{url:"http://www.hao123.com/",city:"beijing"}}); > db.data.insert({name:"ll4la",info:{url:"http://www.114la.com/",city:"dongguan"}});
对字段info创建索引
> db.data.ensureIndex({info: 1});
显示表data上的所有索引
> db.data.getIndexes(); [ { "name" : "_id_", "ns" : "recommender.data", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4befb146b0e29ba1ce20e0bb"), "ns" : "recommender.data", "key" : { "x" : 1 }, "name" : "x_1" }, { "_id" : ObjectId("4befb76bb0e29ba1ce20e0bf"), "ns" : "recommender.data", "key" : { "info" : 1 }, "name" : "info_1" } ]
查找指定的记录,此时会用到索引
> db.data.find({info: {url:"http://www.1616.net/",city:"beijing"}}); { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } }
b.组合索引
建立组合索引
> db.data.ensureIndex({"info.url":1, "info.city":1}); > db.data.getIndexes(); [ { "name" : "_id_", "ns" : "recommender.data", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4befb146b0e29ba1ce20e0bb"), "ns" : "recommender.data", "key" : { "x" : 1 }, "name" : "x_1" }, { "_id" : ObjectId("4befb76bb0e29ba1ce20e0bf"), "ns" : "recommender.data", "key" : { "info" : 1 }, "name" : "info_1" }, { "_id" : ObjectId("4befb9d1b0e29ba1ce20e0c0"), "ns" : "recommender.data", "key" : { "info.url" : 1, "info.city" : 1 }, "name" : "info.url_1_info.city_1" } ]
下面几个操作均会用到索引
> db.data.find({"info.url": "http://www.1616.net/", "info.city": "beijing"}); { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } > db.data.find({"info.url": "http://www.1616.net/"}); { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } }
1表示升序(asc),-1表示降序(desc)
> db.data.find({"info.url": /http:*/i}).sort({"info.url": 1, "info.city": 1}); { "_id" : ObjectId("4befb740b0e29ba1ce20e0be"), "name" : "ll4la", "info" : { "url" : "http://www.114la.com/", "city" : "dongguan" } } { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } { "_id" : ObjectId("4befb723b0e29ba1ce20e0bd"), "name" : "hao123", "info" : { "url" : "http://www.hao123.com/", "city" : "beijing" } } > db.data.find({"info.url": /http:*/i}).sort({"info.url": 1}); { "_id" : ObjectId("4befb740b0e29ba1ce20e0be"), "name" : "ll4la", "info" : { "url" : "http://www.114la.com/", "city" : "dongguan" } } { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } { "_id" : ObjectId("4befb723b0e29ba1ce20e0bd"), "name" : "hao123", "info" : { "url" : "http://www.hao123.com/", "city" : "beijing" } } > db.data.find({"info.url": /http:*/i}).sort({"info.url": -1}); { "_id" : ObjectId("4befb723b0e29ba1ce20e0bd"), "name" : "hao123", "info" : { "url" : "http://www.hao123.com/", "city" : "beijing" } } { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } { "_id" : ObjectId("4befb740b0e29ba1ce20e0be"), "name" : "ll4la", "info" : { "url" : "http://www.114la.com/", "city" : "dongguan" } }
4.组合索引
注意,这里的组合索引与上述3中的b中的组合索引是有点不同的,4里面是对一级字段建立组合索引,而上述3中是对二级字段建立组合索引。
在字段name及info上面创建组合索引
> db.data.ensureIndex({name: 1, info: -1});
当创建组合索引时,字段后面的1表示升序,-1表示降序,是用1还是用-1主要是跟排序的时候或指定范围内查询的时候有关的,具体看下面的英文原文的说明。
When creating an index, the number associated with a key specifies the direction of the index, so it should always be 1 (ascending) or -1 (descending). Direction doesn’t matter for single key indexes or for random access retrieval but is important if you are doing sorts or range queries on compound indexes.
显示所有的索引
> db.data.getIndexes(); [ { "name" : "_id_", "ns" : "recommender.data", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4befb146b0e29ba1ce20e0bb"), "ns" : "recommender.data", "key" : { "x" : 1 }, "name" : "x_1" }, { "_id" : ObjectId("4befb76bb0e29ba1ce20e0bf"), "ns" : "recommender.data", "key" : { "info" : 1 }, "name" : "info_1" }, { "_id" : ObjectId("4befb9d1b0e29ba1ce20e0c0"), "ns" : "recommender.data", "key" : { "info.url" : 1, "info.city" : 1 }, "name" : "info.url_1_info.city_1" }, { "_id" : ObjectId("4befbfcfb0e29ba1ce20e0c1"), "ns" : "recommender.data", "key" : { "name" : 1, "info" : -1 }, "name" : "name_1_info_-1" } ]
下面的排序将用到上面的索引
最后一行的”name” : “ll4la”实际上是”name” : “114la”(就是将数字一写成了字母l),但是我录入的时候写成了”name” : “ll4la”,是我写错了,但是排序的结果是对的。
> db.data.find({"info.url": /http:*/i}).sort({name:1, info: -1}); { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } { "_id" : ObjectId("4befb723b0e29ba1ce20e0bd"), "name" : "hao123", "info" : { "url" : "http://www.hao123.com/", "city" : "beijing" } } { "_id" : ObjectId("4befb740b0e29ba1ce20e0be"), "name" : "ll4la", "info" : { "url" : "http://www.114la.com/", "city" : "dongguan" } }
MongoDB组合索引规则
If you have a compound index on multiple fields, you can use it to query on the beginning subset of fields. So if you have an index on
a,b,c
you can use it query on
a
a,b
a,b,c
如果用过MySQL的话,看起来是不是很熟悉,原理跟MySQL是一样的。
5.唯一索引
往表data中插入一条记录。
> db.data.insert({firstname: "cai", lastname: "huafeng"});
由于表data中只有一记录有字段firstname及lastname,其它的行均没有相应的值,也就是均为null,为null就说明是相同的,而唯一索引是不允许有相同的值的,所以下面创建唯一组合索引时报错了。
所以建立唯一索引时,不管是对单个字段还是多个字段建立索引,则最好每一行均有此字段,否则会报错。
> db.data.find(); { "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" } { "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" } { "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1" } { "_id" : ObjectId("4bee804ba23d558eb6687118"), "x" : 6, "name" : "caihuafeng2" } { "_id" : ObjectId("4bee804ba23d558eb6687119"), "x" : 6, "name" : "caihuafeng3" } { "_id" : ObjectId("4bee804ba23d558eb668711a"), "x" : 6, "name" : "caihuafeng4" } { "_id" : ObjectId("4bee804ba23d558eb668711b"), "x" : 6, "name" : "caihuafeng5" } { "_id" : ObjectId("4bee804ba23d558eb668711c"), "x" : 6, "name" : "caihuafeng6" } { "_id" : ObjectId("4bee804ba23d558eb668711d"), "x" : 6, "name" : "caihuafeng7" } { "_id" : ObjectId("4bee804ba23d558eb668711e"), "x" : 6, "name" : "caihuafeng8" } { "_id" : ObjectId("4bee804ba23d558eb668711f"), "x" : 6, "name" : "caihuafeng9" } { "_id" : ObjectId("4bee804ba23d558eb6687120"), "x" : 6, "name" : "caihuafeng10" } { "_id" : ObjectId("4befb711b0e29ba1ce20e0bc"), "name" : "1616", "info" : { "url" : "http://www.1616.net/", "city" : "beijing" } } { "_id" : ObjectId("4befb723b0e29ba1ce20e0bd"), "name" : "hao123", "info" : { "url" : "http://www.hao123.com/", "city" : "beijing" } } { "_id" : ObjectId("4befb740b0e29ba1ce20e0be"), "name" : "ll4la", "info" : { "url" : "http://www.114la.com/", "city" : "dongguan" } } { "_id" : ObjectId("4befc51ab0e29ba1ce20e0c2"), "firstname" : "cai", "lastname" : "huafeng" } > db.data.ensureIndex({firstname: 1, lastname: 1}, {unique: true}); E11000 duplicate key error index: recommender.data.$firstname_1_lastname_1 dup key: { : null, : null }
下面我们用另外一个表person来进行测试
> db.person.ensureIndex({firstname:1, lastname: 1},{unique: true}); > db.person.insert({firstname: 'cai', lastname: 'huafeng'});
第二次插入同样值的时候报错了,说明唯一索引生效了,其实跟MySQL里面是一样的。
> db.person.insert({firstname: 'cai', lastname: 'huafeng'}); E11000 duplicate key error index: recommender.person.$firstname_1_lastname_1 dup key: { : "cai", : "huafeng" }
6.唯一索引中的重复值处理
删除上述5中的索引,插入两行一样的记录
> db.person.dropIndexes(); { "nIndexesWas" : 2, "msg" : "non-_id indexes dropped for collection", "ok" : 1 } > db.person.find(); { "_id" : ObjectId("4befcda6b0e29ba1ce20e0cf"), "firstname" : "cai", "lastname" : "huafeng" } > db.person.insert({firstname: 'cai', lastname: 'huafeng'}); > db.person.find(); { "_id" : ObjectId("4befcda6b0e29ba1ce20e0cf"), "firstname" : "cai", "lastname" : "huafeng" } { "_id" : ObjectId("4befcef0b0e29ba1ce20e0d1"), "firstname" : "cai", "lastname" : "huafeng" }
如果现在直接在字段firstname及lastname上面创建唯一组合索引的时候肯定会报错,我们来试一试:
> db.person.ensureIndex({firstname: 1, lastname: 1}, {unique: true}); E11000 duplicate key error index: recommender.person.$firstname_1_lastname_1 dup key: { : "cai", : "huafeng" }
查看表person的索引,我们可以看到,新创建的索引没有生成。
> db.person.getIndexes(); [ { "name" : "_id_", "ns" : "recommender.person", "key" : { "_id" : 1 } } ]
可以在第二个json对象加入一项dropDups: true,这样在创建唯一组合索引的时候不会报错,保留文档中第一个重复的值,其它重复的值均删除。
再次测试一下,加入dropDups选项,虽然报错了,但是唯一组合索引已经建立了。
> db.person.ensureIndex({firstname: 1, lastname: 1}, {unique: true, dropDups: true}); E11000 duplicate key error index: recommender.person.$firstname_1_lastname_1 dup key: { : "cai", : "huafeng" } > db.person.getIndexes(); [ { "name" : "_id_", "ns" : "recommender.person", "key" : { "_id" : 1 } }, { "_id" : ObjectId("4befcfd9b0e29ba1ce20e0d3"), "ns" : "recommender.person", "key" : { "firstname" : 1, "lastname" : 1 }, "name" : "firstname_1_lastname_1", "unique" : true, "dropDups" : true } ]
再次查询表person中的记录,发现重复的记录已经自动删除了。
> db.person.find(); { "_id" : ObjectId("4befcda6b0e29ba1ce20e0cf"), "firstname" : "cai", "lastname" : "huafeng" }
MongoDB官方文档的说明
A unique index cannot be created on a key that has duplicate values. If you would like to create the index anyway, keeping the first document the database indexes and deleting all subsequent documents that have duplicate values, add the dropDups option.
db.things.ensureIndex({firstname : 1}, {unique : true, dropDups : true})
7.删除索引
a.删除某个表中的所有索引
To delete all indexes on the specified collection:
db.collection.dropIndexes();
b.删除某个表中的单一索引
To delete a single index:
db.collection.dropIndex({x: 1, y: -1}) > db.data.dropIndex({firstname: 1, lastname: 1}); { "nIndexesWas" : 6, "ok" : 1 }
Running directly as a command without helper:
// note: command was "deleteIndexes", not "dropIndexes", before MongoDB v1.3.2 // remove index with key pattern {y:1} from collection foo db.runCommand({dropIndexes:'foo', index : {y:1}}) // remove all indexes: db.runCommand({dropIndexes:'foo', index : '*'}) > db.person.ensureIndex({firstname: 1, lastname: 1}); > db.runCommand({dropIndexes:'person', index:{firstname:1, lastname:1}}); { "nIndexesWas" : 2, "ok" : 1 }
延伸阅读:
http://www.mongodb.org/display/DOCS/Indexes#Indexes-DocumentsasKeys
http://www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers
http://www.mongodb.org/display/DOCS/Advanced+Queries
相关推荐
在本文中,我们将深入探讨 MongoDB 数据库索引的基础知识、类型、创建方式、使用注意点等方面的内容。 索引基础 ---------- 为什么需要索引?索引可以显著地提高查询性能。例如,在没有索引的情况下,MongoDB 需要...
MongoDB的索引是数据库性能优化的关键因素,与MySQL、Oracle等关系型数据库中的索引原理相似,但具有自身的特性和限制。MongoDB的索引建立在Collection(表)级别,采用B-树数据结构来加速查询和排序操作。 1. 默认...
在MongoDB中,索引对于优化查询性能至关重要,尤其在处理大量数据时。下面将详细介绍MongoDB中不同类型的索引创建、查询及维护。 首先,MongoDB有一个默认的`_id`字段,它扮演着主键的角色。每个集合在创建时都会...
因此,对MongoDB数据库索引构建情况进行全面分析至关重要,以确保系统性能与资源使用的平衡。 首先,我们可以通过`mongostat`工具来实时监测MongoDB的运行状态。`mongostat`每隔一段时间(默认是1秒)会输出各种...
MongoDB支持的索引种类很多,诸如单键索引,复合索引,多键索引,TTL索引,文本索引,空间地理索引等。同时索引的属性可以具有唯一性,即唯一索引。唯一索引用于确保索引字段不存储重复的值,即强制索引字段的唯一性...
11、MongoDB聚合操作及索引使用详解_ev.rar11、MongoDB聚合操作及索引使用详解_ev.rar11、MongoDB聚合操作及索引使用详解_ev.rar11、MongoDB聚合操作及索引使用详解_ev.rar11、MongoDB聚合操作及索引使用详解_ev.rar...
本文将深入探讨MongoDB中创建简单索引的方法及其重要性。 首先,理解索引的概念至关重要。索引是一种特殊的数据结构,它在数据库中用于加速数据检索。在MongoDB中,索引按照特定的字段或字段组合进行排序,使得查询...
在 MongoDB 中,你可以使用 `ensureIndex()` 方法来创建带有命名索引的集合。这个方法接受两个参数:一个是索引的键值对,另一个是包含索引选项的对象。以下是如何创建命名索引的语法: ```javascript db....
在MongoDB中,覆盖索引查询是指查询涉及的所有字段都包含在创建的索引中,这样MongoDB就无需回表(即不需访问原始文档)来获取查询结果,从而显著提高了查询速度。 1. 覆盖索引查询的含义 覆盖索引查询的核心在于,...
MongoDB 是一个流行的开源文档型数据库系统,以其...通过合理地设计和使用索引,可以显著提高 MongoDB 数据库的查询速度和整体性能。对于处理大量数据和复杂查询的业务场景,理解和掌握这些高级索引技术是至关重要的。
- **内存使用**:MongoDB 的索引主要存储在内存中,以提高查询速度。因此,你需要确保索引的大小不超过服务器的可用 RAM。如果索引超出内存限制,MongoDB 将开始使用磁盘上的缓存,这可能导致性能下降。 2. **查询...
在MongoDB中,索引是提高查询性能的关键工具,能够帮助数据库快速定位和排序数据。本篇文章将详细探讨MongoDB中的索引管理以及高级索引概念。 1. **查看索引** MongoDB 提供了两种方法来查看集合上的索引。`db....
覆盖索引是指建立的索引包含了查询所需要的所有字段,这样在执行查询时,MongoDB可以直接从索引中获取数据,而无需回表(即不需访问原始文档)。这样做的好处是显著减少了查询时间,因为索引通常存储在内存中,与从...
这篇文档将深入探讨Spring Data MongoDB 的核心概念和用法。 1. **MongoDB 简介** MongoDB 是一个NoSQL 数据库,使用JSON 样式的文档存储数据,适合处理大规模数据。其特点包括高可用性、可扩展性和灵活性。 2. *...
在实际应用中,可以通过编写脚本或使用MongoDB shell来创建和测试TTL索引。例如,以下脚本创建了一个名为`tltTest`的集合,并插入了三个具有不同`createDate`的文档,然后创建一个TTL索引,使得这些文档在5分钟后...
索引是 MongoDB 中的关键概念,它们能够显著提升查询性能。本篇资料主要涵盖了 MongoDB 的索引使用和查询分析,以下是对这些知识点的详细解释: 1. **explain操作**:`explain` 是 MongoDB 提供的一个命令,用于...
库是MongoDB中数据的最高级别组织单位,类似于SQL中的数据库。集合是库中的逻辑单元,类似表,但不需要预定义模式,这意味着集合内的文档可以有不同结构。文档是MongoDB的基本数据单元,它们类似于JSON对象,可以...
- **Spring Data MongoDB** 支持索引管理,可以通过 `MongoTemplate` 或者 Repository 来创建索引。 - 索引可以显著提高查询性能,特别是在大型数据集上。 #### 八、聚合框架支持 - **Spring Data MongoDB** 支持 ...