MongoDB基础之六 索引

 

一 . 索引概述和基本操作

1. 索引提高查询速度,降低写入速度,权衡常用的查询字段,不必在太多列上建索引
2. 在mongodb中,索引可以按字段升序/降序来创建,便于排序
3. 默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引.

常用命令:
查看当前索引状态: db.collection.getIndexes();

创建普通的单列索引:db.collection.ensureIndex({field:1/-1}); 1是升续 2是降续

删除单个索引
db.collection.dropIndex({filed:1/-1});

一下删除所有索引
db.collection.dropIndexes();

创建多列索引 db.collection.ensureIndex({field1:1/-1, field2:1/-1});

 

例子: 

 1 > for (var i = 1;i<=1000;i++){
 2 ... db.stu.insert({sn:i,name:'student'+i})
 3 ... };
 4 > 
 5 > 
 6 > db.stu.find().count();
 7 1000
 8 > db.stu.find({sn:99});
 9 { "_id" : ObjectId("574271a9addef29711337c28"), "sn" : 99, "name" : "student99" }
10 > db.stu.find({sn:99}).explain();
11 {
12 "cursor" : "BasicCursor", -- 无索引相当于mysql的全表扫描
13 "isMultiKey" : false, 
14 "n" : 1,
15 "nscannedObjects" : 1000, -- 扫描了1000行
16 ....
17 
18 > db.stu.ensureIndex({sn:1}); --创建索引
19 > db.stu.find({sn:99}).explain();
20 {
21 "cursor" : "BtreeCursor sn_1", --使用了索引
22 "isMultiKey" : false,
23 "n" : 1,
24 "nscannedObjects" : 1, --只用扫描一行
25 ...
26 }
27 
28 
29 > db.stu.getIndexes(); --查询索引
30 [
31 {
32 "v" : 1,
33 "key" : {
34 "_id" : 1 -- 默认创建 正序
35 },
36 "ns" : "test.stu",
37 "name" : "_id_"
38 },
39 {
40 "v" : 1,
41 "key" : {
42 "sn" : 1
43 },
44 "ns" : "test.stu",
45 "name" : "sn_1"
46 }
47 ]
48 
49 
50 > db.stu.ensureIndex({sn:1,name:1});
51 > 
52 > 
53 > db.stu.getIndexes();
54 [
55 {
56 "v" : 1,
57 "key" : {
58 "_id" : 1
59 },
60 "ns" : "test.stu",
61 "name" : "_id_"
62 },
63 {
64 "v" : 1,
65 "key" : {
66 "sn" : 1
67 },
68 "ns" : "test.stu",
69 "name" : "sn_1"
70 },
71 {
72 "v" : 1,
73 "key" : {
74 "sn" : 1,
75 "name" : 1
76 },
77 "ns" : "test.stu",
78 "name" : "sn_1_name_1"
79 }
80 ]

 

 

二. 子文档索引

     指向下级嵌套的文档的索引

 1 > db.shop.insert({name:'Nokia',spc:{weight:120,area:'taiwan'}});
 2 > db.shop.insert({name:'Nokia',spc:{weight:100,area:'korea'}});
 3 
 4 > db.shop.find({'spc.area':'taiwan'});
 5 { "_id" : ObjectId("5743d662addef29711337fb0"), "name" : "Nokia", "spc" : { "weight" : 120, "area" : "taiwan" } }
 6 
 7 
 8 > db.shop.ensureIndex({'spc.area,1'});
 9 Tue May 24 12:29:58.823 SyntaxError: Unexpected token }
10 > db.shop.ensureIndex({'spc.area':1});
11 > 
12 > db.shop.getIndexes();
13 [
14 {
15 "v" : 1,
16 "key" : {
17 "_id" : 1
18 },
19 "ns" : "test.shop",
20 "name" : "_id_"
21 },
22 {
23 "v" : 1,
24 "key" : {
25 "spc.area" : 1
26 },
27 "ns" : "test.shop",
28 "name" : "spc.area_1"
29 }
30 ]
31 >

 

 

三.  唯一索引

 1 > show tables;
 2 shop
 3 stu
 4 system.indexes
 5 > 
 6 > 
 7 > db.tea.insert({email:'a@163.com'})
 8 > db.tea.insert({email:'b@163.com'})
 9 > 
10 > db.tea.getIndexes();
11 [
12 {
13 "v" : 1,
14 "key" : {
15 "_id" : 1
16 },
17 "ns" : "test.tea",
18 "name" : "_id_"
19 }
20 ]
21 > 
22 > 
23 > 
24 > db.tea.ensureIndex({email:1},{unique:true});
25 > 
26 > 
27 > db.tea.insert({email:'c@163.com'})
28 > db.tea.insert({email:'c@163.com'})
29 E11000 duplicate key error index: test.tea.$email_1 dup key: { : "c@163.com" }
30 >

 

 

四. 稀疏索引

稀疏索引的特点------如果针对field做索引,针对不含field列的文档,将不建立索引.
与之相对,普通索引,会把该文档的field列的值认为NULL,并建索引.
适宜于: 小部分文档含有某列时.

db.collection.ensureIndex({field:1/-1},{sparse:true})

 

 1 -- 模拟数据
 2 > db.tea.insert({});
 3 > db.tea.find();
 4 { "_id" : ObjectId("5743d98aaddef29711337fb4"), "email" : "a@163.com" }
 5 { "_id" : ObjectId("5743d98daddef29711337fb5"), "email" : "b@163.com" }
 6 { "_id" : ObjectId("5743d9cfaddef29711337fb7"), "email" : "c@163.com" }
 7 { "_id" : ObjectId("5743dc98addef29711337fbc") }
 8 
 9  
10 
11 --稀疏索引下查不到数据
12 > db.tea.ensureIndex({email:1},{sparse:true});
13 > db.tea.find({email:null});
14 >
15 
16 > db.tea.dropIndexes();
17 {
18 "nIndexesWas" : 2,
19 "msg" : "non-_id indexes dropped for collection",
20 "ok" : 1
21 }
22 
23 --普通索引能查到
24 > db.tea.ensureIndex({email:1});
25 > db.tea.find({email:null});
26 { "_id" : ObjectId("5743dc98addef29711337fbc") }

 

 总结:
如果分别加普通索引,和稀疏索引,
对于最后一行的email分别当成null 和 忽略最后一行来处理.
根据{email:null}来查询,前者能查到,而稀疏索引查不到最后一行.

 

五. 创建哈希索引(2.4新增的)

哈希索引速度比普通索引快,但是,无能对范围查询进行优化.
适宜于---随机性强的散列

db.collection.ensureIndex({file:'hashed'});

 1 > db.tea.ensureIndex({email:'hashed'});
 2 > db.tea.find({email:'a@163.com'}).explain();
 3 {
 4 "cursor" : "BtreeCursor email_hashed",
 5 "isMultiKey" : false,
 6 "n" : 1,
 7 "nscannedObjects" : 1,
 8 "nscanned" : 1,
 9 "nscannedObjectsAllPlans" : 1,
10 "nscannedAllPlans" : 1,
11 "scanAndOrder" : false,
12 "indexOnly" : false,
13 "nYields" : 0,
14 "nChunkSkips" : 0,
15 "millis" : 0,
16 "indexBounds" : {
17 "email" : [
18 [
19 NumberLong("2069420833715827975"),
20 NumberLong("2069420833715827975")
21 ]
22 ]
23 },
24 "server" : "localhost.localdomain:27017"
25 }
26 >

 

六. 重建索引

一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此.
可以通过索引的重建,减少索引文件碎片,并提高索引的效率.
类似mysql中的optimize table

db.collection.reIndex()

 1 > db.tea.reIndex();
 2 {
 3 "nIndexesWas" : 2,
 4 "msg" : "indexes dropped for collection",
 5 "nIndexes" : 2,
 6 "indexes" : [
 7 {
 8 "key" : {
 9 "_id" : 1
10 },
11 "ns" : "test.tea",
12 "name" : "_id_"
13 },
14 {
15 "key" : {
16 "email" : "hashed"
17 },
18 "ns" : "test.tea",
19 "name" : "email_hashed"
20 }
21 ],
22 "ok" : 1
23 }

 

posted @ 2016-05-24 13:13  chinesern  阅读(1457)  评论(1编辑  收藏  举报