MongoDB---索引(二)

2014-11-24 10:23:43 · 作者: · 浏览: 1
: true }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f04"), "username" : "tttttt", "age" : 5
4, "isactive" : true }
用户名按照字母升序排列,同名的组按照年龄升序排列.
如果以{"username":1,"age":-1}这种方式创建索引,MongoDB会按如下方式组织:
> db.refactor.find().hint({"username":1,"age":-1})
{ "_id" : ObjectId("500231f4218b8ef3edbc6f01"), "username" : "aaaaa", "age" : 34
, "isactive" : true }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f00"), "username" : "aaaaa", "age" : 24
, "isactive" : false }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f05"), "username" : "bbbbb", "age" : 24
, "isactive" : false } www.2cto.com
{ "_id" : ObjectId("500231f4218b8ef3edbc6eff"), "username" : "refactor", "age" :
30, "isactive" : false }
{ "_id" : ObjectId("500231f4218b8ef3edbc6efe"), "username" : "refactor", "age" :
24, "isactive" : true }
{ "_id" : ObjectId("500231f6218b8ef3edbc6f07"), "username" : "rrrrr", "age" : 54
, "isactive" : false }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f06"), "username" : "rrrrr", "age" : 24
, "isactive" : true }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f02"), "username" : "sssssss", "age" :
24, "isactive" : true }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f04"), "username" : "tttttt", "age" : 5
4, "isactive" : true }
{ "_id" : ObjectId("500231f4218b8ef3edbc6f03"), "username" : "tttttt", "age" : 2
4, "isactive" : true }
用户名按照字母升序排列,同名的组按照年龄降序排列.
一般来说,如果索引包含了N个键,则对于前几个键的查询都能利用索引,如:有个索引{"a":1,"b":1,"c":1,"d":1}
实际上是有了{"a":1},{"a":1,"b":1},{"a":1,"b":1,"c":1}索引,但是使用{"b":1},{"a":1,"c":1}等索引的查询不会被优化.
只有使用索引前部查询才能使用该索引.
MongoDB的查询优化器会从排查询项的顺序,以便利用索引,如查询{"username":"refactor","age":24}的时候,已经有了
{"age":1,"username":1}的索引,MongoDB会自己找到并利用它.
创建索引的缺点是每次插入,更新,删除都会产生额外的开销,因为数据库不但需要执行这些操作,还要将这些操作在集合的索引中
标记.因此,尽可能少的创建索引.
有些时候,最有效的查询是不实用查询,一般来说,要是查询要返回集合中一半以上的结果,用表扫描会比几乎每条文档都要
索引要快,所以,查询是否存在某个键,或者检查摸个布尔类型的值是真是假,就没有必要利用索引.
www.2cto.com
2.扩展索引
假设有个集合存储了用户的状态信息.现在要查询用户和日期,取出某一用户最近的状态.我们可能会建立
如下索引:
db.users.ensureIndex({"user":1,"date":-1})
这会使对用户和日期的查询非常快,但是并不是最好的方式.
因为应用会有数百万的用户,每人每天都有数十条状态更新.若是每条用户状态的索引值咱用类似一页纸的
磁盘控件,那么对每次"最新状态"的查询,数据库将会将不同的页载入内存.若是站点太热门,内存放不下所有
索引,就会很慢.要是改变索引的顺序{"date":-1,"user":1},则数据库可以将最后几天的索引保存在内存中,
可以有效的减少内存交换,这样查询任何用户的最新状态都会快很多.
3.索引内嵌文档中的键
为内嵌文档的键创建索引和为普通的键创建索引没有什么区别.
db.blog.insert(
  {
    "title":"refactor's blog",
    "Content":"refactor's blog test",
    "author":
    {
      "name":"refactor",
      "email":"295240648@163.com"
    }  
  } www.2cto.com
)
为author.name创建索引
db.blog.ensureIndex({"author.name":1})
对内嵌文档的键索引和普通键索引没有区别,两者可以联合组成复合索引.
3.为排序创建索引
随着集合的增长,需要针对查询中大量的排序做索引.如果对没有索引的键调用sort,MongoDB需要将所有数据
提取到内存中来排序.因此,可以做无索引排序是有个上限的,即不可能在内存中对T级别的数据排序.按照排序来索引
以便MongoDB按照顺序提取数据,这样就能排序大规模数据,而不必担心用光内存.
4.索引名称
集合中的每个索引都有一个字符串类型的名字,来唯一标识索引,服务器通过这个名字来删除或操作索引.默认情况下,
索引名类似 keyname1_dir1_keyname2_dir2这种形式,其中keyname代表索引的键,dir代表索引的方向(1或-1).
可以通过ensureIndex来指定索引的名称.
如:
db.blog.ensureIndex({"author.name":1},{"name":"author_name_index"})
注意不能修改,只能删除索引,再重建.
索引名有字符个数的限制,所以特别复杂的索引在创建时一定要使用自定义的名字,可以用getLastError来检查索引
是否成功创建了或未创建成功的原因.
5.唯一索引
唯一索引可以确保集合的每一个文档的指定键都有唯一值.如果想保证文档的username键都有不同的值:
db.refac