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 }