1 mongoDB索引的管理
db.userinfos.insertMany([ {_id:1, name: "張三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]}, {_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]}, {_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]}, {_id:4, name: "趙六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] }, {_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京' }, {_id:6, name: "周八", age: 28,roles:["gen"], address:'上海' } ]);
索引的增刪改查還是十分簡單的,我們看一下索引管理的幾個方法:
//建立索引,值1表示正序排序,-1表示倒序排序 db.userinfos.createIndex({age:-1}) //檢視userinfos中的所有索引 db.userinfos.getIndexes() //刪除特定一個索引 db.userinfos.dropIndex({name:1,age:-1}) //刪除所有的索引(主鍵索引_id不會被刪除) db.userinfos.dropIndexes() //如果我們要修改一個索引的話,可以先刪除索引然後在重新新增。
2 mongoDB中常用的索引型別
1 單鍵索引
單鍵索引(Single Field Indexes)顧名思義就是單個欄位作為索引列,mongoDB的所有collection預設都有一個單鍵索引_id,我們也可以對一些經常作為過濾條件的欄位設定索引,如給age欄位新增一個索引,語法十分簡單:
//給age欄位新增升序索引 db.userinfos.createIndex({age:1})
其中{age:1}中的1表示升序,如果想設定倒序索引的話使用 db.userinfos.createIndex({age:-1}) 即可。我們通過explain()方法檢視查詢計劃,如下圖,看到查詢age=23的document時使用了索引,如果沒有使用索引的話stage=COLLSCAN。
因為document的儲存是bson格式的,我們也可以給內建物件的欄位新增索引,或者將整個內建物件作為一個索引,語法如下:
//1.內嵌物件的某一欄位作為索引 //在ename.firstname欄位上新增索引 db.userinfos.createIndex({"ename.firstname":1}) //使用ename.firstname欄位的索引查詢 db.userinfos.find({"ename.firstname":"san"}) //2.整個內嵌物件作為索引 //給整個ename欄位新增索引 db.userinfos.dropIndexes() //使用ename欄位的索引查詢 db.userinfos.createIndex({"ename":1})
2 複合索引
複合索引(Compound Indexes)指一個索引包含多個欄位,用法和單鍵索引基本一致。使用複合索引時要注意欄位的順序,如下新增一個name和age的複合索引,name正序,age倒序,document首先按照name正序排序,然後name相同的document按age進行倒序排序。mongoDB中一個複合索引最多可以包含32個欄位。
//新增複合索引,name正序,age倒序 db.userinfos.createIndex({"name":1,"age":-1}) //過濾條件為name,或包含name的查詢會使用索引(索引的第一個欄位) db.userinfos.find({name:'張三'}).explain() db.userinfos.find({name:"張三",level:10}).explain() db.userinfos.find({name:"張三",age:23}).explain() //查詢條件為age時,不會使用上邊建立的索引,而是使用的全表掃描 db.userinfos.find({age:23}).explain()
執行查詢時查詢計劃如下:
3 多鍵索引
多鍵索引(mutiKey Indexes)是建在陣列上的索引,在mongoDB的document中,有些欄位的值為陣列,多鍵索引就是為了提高查詢這些陣列的效率。看一個栗子:準備測試資料,classes集合中新增兩個班級,每個班級都有一個students陣列,如下:
db.classes.insertMany([ { "classname":"class1", "students":[{name:'jack',age:20}, {name:'tom',age:22}, {name:'lilei',age:25}] }, { "classname":"class2", "students":[{name:'lucy',age:20}, {name:'jim',age:23}, {name:'jarry',age:26}] }] )
為了提高查詢students的效率,我們使用 db.classes.createIndex({'students.age':1}) 給students的age欄位新增索引,然後使用索引,如下圖:
4 雜湊索引
雜湊索引(hashed Indexes)就是將field的值進行hash計算後作為索引,其強大之處在於實現O(1)查詢,當然用雜湊索引最主要的功能也就是實現定值查詢,對於經常需要排序或查詢範圍查詢的集合不要使用雜湊索引。
3 mongoDB中常用的索引屬性
1 唯一索引
唯一索引(unique indexes)用於為collection新增唯一約束,即強制要求collection中的索引欄位沒有重複值。新增唯一索引的語法:
//在userinfos的name欄位新增唯一索引 db.userinfos.createIndex({name:1},{unique:true})
看一個使用唯一索引的栗子:
2 區域性索引
區域性索引(Partial Indexes)顧名思義,只對collection的一部分新增索引。建立索引的時候,根據過濾條件判斷是否對document新增索引,對於沒有新增索引的文件查詢時採用的全表掃描,對新增了索引的文件查詢時使用索引。使用方法也比較簡單:
//userinfos集合中age>25的部分新增age欄位索引 db.userinfos.createIndex( {age:1}, { partialFilterExpression: {age:{$gt: 25 }}} ) //查詢age<25的document時,因為age<25的部分沒有索引,會全表掃描查詢(stage:COLLSCAN) db.userinfos.find({age:23}) //查詢age>25的document時,因為age>25的部分建立了索引,會使用索引進行查詢(stage:IXSCAN) db.userinfos.find({age:26})
當查詢age=23的記錄時,stage=COLLSCAN,當查詢age=26的記錄時,使用了索引,如下:
2 稀疏索引
稀疏索引(sparse indexes)在有索引欄位的document上新增索引,如在address欄位上新增稀疏索引時,只有document有address欄位時才會新增索引。而普通索引則是為所有的document新增索引,使用普通索引時如果document沒有索引欄位的話,設定索引欄位的值為null。
稀疏索引的建立方式如下,當document包含address欄位時才會建立索引:
//建立在address上建立稀疏索引 db.userinfos.createIndex({address:1},{sparse:true})
看一個使用稀疏索引的栗子:
4 TTL索引
TTL索引(TTL indexes)是一種特殊的單鍵索引,用於設定document的過期時間,mongoDB會在document過期後將其刪除,TTL非常容易實現類似快取過期策略的功能。我們看一個使用TTL索引的栗子:
//新增測試資料 db.logs.insertMany([ {_id:1,createtime:new Date(),msg:"log1"}, {_id:2,createtime:new Date(),msg:"log2"}, {_id:3,createtime:new Date(),msg:"log3"}, {_id:4,createtime:new Date(),msg:"log4"} ]) //在createtime欄位新增TTL索引,過期時間是120s db.logs.createIndex({createtime:1}, { expireAfterSeconds: 120 }) //logs中的document在建立後的120s後過期,會被mongoDB自動刪除
注意:TTL索引只能設定在date型別欄位(或者包含date型別的陣列)上,過期時間為欄位值+exprireAfterSeconds;document過期時不一定就會被立即刪除,因為mongoDB執行刪除任務的時間間隔是60s;capped Collection不能設定TTL索引,因為mongoDB不能主動刪除capped Collection中的document。
小結
本節介紹了mongoDB中常用的索引和索引屬性,索引對提升資料檢索的速度十分重要,在資料量比較大的時候一般都要在collection上建立索引。mongoDB提供的索引種類很豐富,總會有幾種適用於我們的業務,除了上邊介紹的索引外,mongoDB還支援text index和一些地理位置相關的索引,這裡不再介紹,有興趣的小夥伴可以到官網 研究下。如果文中有錯誤的話,希望大家可以指出,我會及時修改,謝謝。