快速掌握mongoDB(三)——mongoDB的索引詳解

1 mongoDB索引的管理

  本節介紹mongoDB中的索引,熟悉mysql/sqlserver等關係型數據庫的小夥伴應該都知道索引對優化數據查詢的重要性。咱們先簡單瞭解一下索引:索引的本質就是一個排序的列表,在這個列表中存儲着索引的值和包含這個值的數據(數據row或者document)的物理地址,索引能夠大大加快查詢的速度,這是由於使用索引後能夠再也不掃描全表來定位某行的數據,而是先經過索引表找到該行數據對應的物理地址(多數爲B-tree查找),而後經過地址來訪問相應的數據。
  索引能夠加快數據檢索、排序、分組的速度,減小磁盤I/O,可是索引也不是越多越好,由於索引自己也是數據表,須要佔用存儲空間,同時索引須要數據庫進行維護,當咱們對索引列的值進行增改刪操做時,數據庫須要更新索引表,這會增長數據庫的壓力。
咱們要根據實際狀況來判斷哪些列適合添加索引,哪些列不適合添加索引,通常遵循的規律以下:
  主/外鍵列,主鍵用於強制該列的惟一性和組織表中數據的排列結構;外鍵能夠加快鏈接的速度;
  常常用於比較的類(大於小於等於等),由於索引已經排序,值就是大於/小於的分界點;
  常常進行範圍搜索,由於索引已經排序,其指定的範圍是連續的;
  常常進行排序的列,由於索引已經排序,這樣查詢能夠利用索引的排序,加快排序查詢時間;
  常常進行分組的列,由於索引已經排序,同一個值的全部數據地址會彙集在一塊,很方便分組。
咱們看一下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:'上海' } ]); 

  索引的增刪改查仍是十分簡單的,咱們看一下索引管理的幾個方法:html

//建立索引,值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字段添加一個索引,語法十分簡單:mysql

//給age字段添加升序索引
  db.userinfos.createIndex({age:1})

  其中{age:1}中的1表示升序,若是想設置倒序索引的話使用 db.userinfos.createIndex({age:-1}) 便可。咱們經過explain()方法查看查詢計劃,以下圖,看到查詢age=23的document時使用了索引,若是沒有使用索引的話stage=COLLSCAN。sql

  由於document的存儲是bson格式的,咱們也能夠給內置對象的字段添加索引,或者將整個內置對象做爲一個索引,語法以下:mongodb

//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字段添加索引,而後使用索引,以下圖:app

 4 哈希索引

  哈希索引(hashed Indexes)就是將field的值進行hash計算後做爲索引,其強大之處在於實現O(1)查找,固然用哈希索引最主要的功能也就是實現定值查找,對於常常須要排序或查詢範圍查詢的集合不要使用哈希索引。sqlserver

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和一些地理位置相關的索引,這裏再也不介紹,有興趣的小夥伴能夠到官網 研究下。若是文中有錯誤的話,但願你們能夠指出,我會及時修改,謝謝。

 

原文出處:https://www.cnblogs.com/wyy1234/p/11032163.html

相關文章
相關標籤/搜索