索引常常用来大幅度的提升查询的性能。 考虑应用程序的查询种类是非常重要的事情,因此你就要定义相关的索引。
决定了之后,在MongoDB中创建索引是非常简单的。
基础
索引就是collection中一个document指定一个字段值的数据结构。MongoDB查询优化器可以使用这个数据结构快速分类整理以及排序document。一般来说,索引的实现是B-TREE。
在Shell中,你可以使用ensureIndex()来创建索引,并且指定要索引一个或多个字段。
我们在j字段上创建一个索引
db.things.ensureIndex({j:1}); 如果索引不存在,ensureIndex就创建索引。 一旦索引被创建了,匹配索引字段的查询是非常快速的。 没有索引的话,MongoDB必须检查每个document要查询的字段。 db.things.find({j : 2}); // 快速,使用了索引。 db.things.find({x : 3}); // 慢- 检查所有的document,因为x没有被索引。
你可以使用db.things.getIndexes();来查看索引信息。
默认索引
_id字段默认被添加了索引。这个索引也不能被删除。_id索引是唯一的。Capped Collections并不会默认创建索引。
Embedded Keys
你甚至可以向embedded document的字段创建索引。例子
db.things.ensureIndex({"address.city": 1}) document做为key索引的字段可以为任意类型,包括了document类型。 db.factories.insert( { name: "xyz", metro: { city: "New York", state: "NY" } } ); db.factories.ensureIndex( { metro : 1 } ); //这个查询可以使用上面创建的索引。 db.factories.find( { metro: { city: "New York", state: "NY" } } ); //等同于 db.factories.find( { metro: { $gte : { city: "New York" } } } ); //metro内的字段顺序错误,不能应用这个索引。 db.factories.find( { metro: { state: "NY" , city: "New York" } } ); 也可以创建这个document内字段的组合索引。 db.factories.ensureIndex( { "metro.city" : 1, "metro.state" : 1 } ); //以下查询可以使用上面创建的索引。 db.factories.find( { "metro.city" : "New York", "metro.state" : "NY" } ); db.factories.find( { "metro.city" : "New York" } ); db.factories.find().sort( { "metro.city" : 1, "metro.state" : 1 } ); db.factories.find().sort( { "metro.city" : 1 } ) 下面谈谈这两种方法的优劣势。 当使用整个document做为索引,顺序就默认定义了,升序。 当使用组合索引,你可以混合升序和降序的key,并且查询优化器使用该索引也需要匹配查询中的首个字段。
数组当索引的键为数组的时候,MongoDB会索引数组中每个元素。 |
1.6+新特性 目前,可以组合索引中的字段条件可以为等值的组合或者范围查询。 如果索引中的首个字段存在于查询中,那么查询优化器可能会选用这个索引。 如果索引中的首个字段不存在于查询中,如果显式使用hint才可以使用这个索引。 索引的子集字段在查询中,这种索引可以用在很多地方。 做为一般的规则来说,对于指定的查询,最又索引就是那些要查询的字段。 |
目前的限制 稀疏索引只能在一个字段上创建. SERVER-2193 |
1.7.4的新功能。
db.people.ensureIndex({title : 1}, {sparse : true})
db.people.save({name:"Jim"})
db.people.save({name:"Sarah", title:"Princess"})
db.people.find({title:{$ne:null}}).sort({title:1})
// 只返回 Sarah的文档
你可以把sparse何unique索引结合起来,来给那些没有丢失字段的document加以唯一性约束。
db.things.ensureIndex({firstname: 1}, {unique: true});
db.things.save({lastname: "Smith"});
/这个操作就会发生错误。
db.things.save({lastname: "Jones"});
删除指定collection的索引语句为
db.collection.dropIndexes();
删除一个单独的索引
db.collection.dropIndex({x: 1, y: -1})
直接运行一个命令
// 注意:1.3.2之前 命令是"deleteIndexes", 而不是 "dropIndexes"
// 从foo collection中删除 {y:1}索引
db.runCommand({dropIndexes:'foo', index : {y:1}})
// 删除所有索引
db.runCommand({dropIndexes:'foo', index : '*'})
reIndex会重新创建索引
db.myCollection.reIndex()
// 等同于:
db.runCommand( { reIndex : 'myCollection' } )
一般来说用不上。如果collection大小增长太快或者索引占用空间看起来很大,就可以使用reIndex。
修复数据库会重新创建索引。