mongodb学习记录之三:索引

索引就是用来加速查询的

现在要按照某个键进行查询:

>db.students.find({"name":"李明"});
							

当查询中仅含有一个键时,可以对该键创建索引,以提高查询速度。

本例中对name创建索引,创建索引使用ensureIndex方法

>db.students.ensureIndex({"name":1})
							

对于同一个集合,同样的索引只需要创建一次即可。

对某个键创建的索引会加速对该键的查询,而对其他键的查询并不起作用,即使查询中包含了索引的键。

实践证明,一定要创建查询中用到的所有键的索引。

索引的方向

如果有多个键,就得考虑索引的方向。

例如还是之前的students集合

{"_id":...,"name":"smith","age":48,"uid":1}
{"_id":...,"name":"smith","age":32,"uid":2}
{"_id":...,"name":"joe","age":36,"uid":3}
{"_id":...,"name":"joe","age":35,"uid":4}
{"_id":...,"name":"john","age":33,"uid":5}
							

如果按照{name:1,age:-1}这种方式创建索引,mongo会按照如下方式组织:

{"_id":...,"name":"joe","age":36,"uid":3}
{"_id":...,"name":"joe","age":35,"uid":4}
{"_id":...,"name":"john","age":33,"uid":5}
{"_id":...,"name":"smith","age":48,"uid":1}
{"_id":...,"name":"smith","age":32,"uid":2}
							

用户名按照字母升序排序,age按照降序排序

一般来说,如果索引包含n个键,则对于前几个键的查询都会有帮助。

例如,索引为{"a":1,"b":1,"c":1,...,"z":1},实际上是有了{"a":1}{"a":1,"b":1}{"a":1,"b":1,"c":1}...等的索引。

但是使用{"b":1}{"a":1,"c":1}却不被优化。

创建索引的缺点就是,每次插入,更新和删除时都会产生额外的开销。这是因为数据库不仅要执行这些操作,还要将这些操作在集合的索引中标记。因此要尽可能少的创建索引。

为内嵌文档创建索引

为内嵌文档创建索引和为普通的键创建索引没有什么区别。例如,要想按日期搜索博客的评论,可以在由内嵌的comments文档组成的数组中对date键创建索引

>db.blog.ensureIndex({"comments.date":1})
							

为排序创建索引

在数据量很大时,如果没有对索引进行排序,那么mongodb需要将所有的数据提取到内存进行排序。

唯一索引可以确保文档中指定的键都有唯一值。

>db.students.ensureIndex({"name":1},{"unique":true})
							

这样我们便给name键做了唯一索引。确保name键不能出现重复的值

当一个记录被插入到唯一性索引文档时,缺失的字段会以null为默认值被插入文档

上面这句话有点迷糊,下面写个例子测试一下就明白了。

新建一个person集合,结构如下:

{
	"_id" : ObjectId("5332777c74d09b6a7018fbf4"),
	"name" : "张明明",
	"sex" : "男",
	"age" : 23,
	"books" : [
		"诗人的世界",
		"Java编程思想",
		"HTML5实战"
	]
}
							

有5个键,下面我们在name和age上创建一个唯一索引

>db.person.ensureIndex({"name":1,"age":-1},{"unipue":true})
							

创建完毕后用getIndexes查看刚才创建的索引。

{
        "v" : 1,
        "key" : {
                "name" : 1,
                "age" : -1
        },
        "unique" : true,
        "ns" : "test.person",
        "name" : "name_1_age_-1"
}
							

下面我们插入数据进行测试.第一条数据已完整的插入,如上

我们先插入一条姓名为"张明",年龄为23的文档,成功。结果如下:

db.person.insert({name:"张明",age:23,sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})	
结果:							
{"name" : "张明明", "sex" : "男", "age" : 23, "books" : [  "诗人的世界","Java编程思想",  "HTML5实战" ] }
{"name" : "张明", "age" : 23, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
							

下面我们再插入一条:

db.person.insert({name:"张明",age:22,sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})
结果:
{ "name" : "张明明", "sex" : "男", "age" : 23, "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ]
{ "name" : "张明", "age" : 23, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : "张明", "age" : 22, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
							

我们再插入一条姓名和年龄都相同的数据看看:

db.person.insert({name:"张明",age:22,sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})
结果:
E11000 duplicate key error index: test.person.$name_1_age_-1  dup key: { : "张明", : 22.0 }
							

上面两个例子可以看出,创建了唯一索引后,创建索引的键组合是唯一的,不能重复的。

如果创建了索引后,在插入时不包含索引的键会怎样?

db.person.insert({age:22,sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})
结果:
{ "name" : "张明明", "sex" : "男", "age" : 23, "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : "张明", "age" : 23, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : "张明", "age" : 22, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "age" : 22, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
							
db.person.insert({name:null,age:null,sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})
结果:
{ "name" : "张明明", "sex" : "男", "age" : 23, "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : "张明", "age" : 23, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : "张明", "age" : 22, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "age" : 22, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
{ "name" : null, "age" : null, "sex" : "男", "books" : [  "诗人的世界",  "Java编程思想",  "HTML5实战" ] }
							

这时候我们再插入一条数据,没有姓名,没有年龄:

db.person.insert({sex:"男",books:["诗人的世界","Java编程思想","HTML5实战"]})
结果:
E11000 duplicate key error index: test.person.$name_1_age_-1  dup key: { : null, : null }
							

由此我们就可以慢慢理解了,当一个键值为null时,其实和没有这个键是一样的。这也就是说,如果在插入时,唯一索引缺失的键会以null为默认值

消除重复

有时候我们在创建索引之前,数据库中已存在了重复的键值,此时创建索引失败。我们可以使用dropDups消除重复,只保留发现的第一个文档,删除其他重复的文档,然后创建索引。

db.person.ensureIndex({"name":1,"age":-1},{"unique":true,"dropDups":true})
							
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值