MongoDB索引與優化詳解

在MongoDB中經過創建索引能夠進行高效的查詢,若是沒有索引MongoDB將會掃描整個集合與查詢的條件進行匹配,這對於性能會形成很大的消耗。

技術博客: Node.js技術棧git

快速導航

面試指南

  • 生產環境如何正確建立索引? ,參考:#

Mongodb索引類型

MongoDB提供了不一樣的索引類型支持在不一樣的業務場景進行查詢

1. _id索引

絕大多數集合默認創建索引,對於每一個插入的數據,MongoDB都會生成一條惟一的_id字段。

例如新建立一個集合時github

db.demo_admin2.insert({x:1})
db.demo_admin2.getIndexes() # 查看集合索引,可看到_id索引

2. 單鍵索引

是最普通的索引,單鍵索引不會自動建立

例如一條記錄形式爲:{x:1,y:2,z:3},只要在x字段上創建索引以後,就能夠用x爲條件進行查詢面試

db.demo_admin2.ensureIndex({x:1}) # 建立索引
db.demo_admin2.find({x:1}); # 使用索引查詢

3. 多鍵索引

多鍵索引與單鍵索引區別在於多鍵索引的值具備多個記錄,是一個數組
db.demo_admin2.insert({x:[1,2,3,4]})

4. 複合索引

當查詢條件爲多個時,須要創建複合索引

插入記錄{'x':1,'y':2,'z':3}mongodb

db.demo_admin2.insert({'x':1,'y':2,'z':3});

建立索引shell

db.demo_3.ensureIndex({x:1,y:1}) # 1升序,-1降序

使用{x:1,y:1}做爲條件進行查詢數據庫

db.demo_admin2.find({x:1,y:2})

5. 過時索引

指在一段時間後會過時的索引,此索引過一段時間會過時,索引過時後,相應的數據會被刪除,適合存儲一些在一段時間以後會失效的數據,好比用戶登陸信息,這樣就不須要用到session了。

5.1 建立過時索引數組

創建索引的時候須要多用一個參數,指定索引的有效時間——expireAfterSeconds,單位爲秒

以下示例爲time字段建立過時索引session

db.demo_3.ensureIndex({time:1},{expireAfterSeconds:10})

5.2 過時索引限制性能

  • 過時索引字段值必須是指定的時間類型,必須是ISODate或ISODate數組,不能使用時間戳,不然不能被自動刪除。
  • 若是指定了ISODate數組,則按照最小的時間進行刪除。 過時索引不能是複合索引。
  • 刪除時間不是精確的,刪除過程是由後臺程序每60s跑一次,並且刪除也須要一些時間,因此存在偏差。
db.demo_3.ensureIndex({time:1},{expireAfterSeconds:30}
db.demo_3.insert({time:new Date()});

6. 全文索引

在mongodb中每一個集合只容許建立一個索引,所以不用擔憂存在多個索引形成衝突的問題。

6.1 全文索引建立測試

全文索引建立方法與建立單鍵索引、複合索引相似。value換成'text',$**匹配集合下全部

爲一個字段建立全文索引

db.articles.ensureIndex({key:"text"})

爲多個字段建立全文索引

db.articles.ensureIndex({key_1:"text"},{key_2:"text"})

爲集合中全部的字段建立全文索引

db.articles.ensureIndex({"$**":"text"})

6.2 實例

創建索引

db.article.ensureIndex({"article":"text"})
db.articles.find({$text:{$search:"coffee"}})
db.articles.find({$text:{$search:"aa bb cc"}}) # 包含aa或bb或cc的數據
db.articles.find({$text:{$search:"aa bb -cc"}}) # 同時包含aa、bb且不包含cc的數據
db.articles.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}})# 同時包含aa、bb、cc的數據(用""包裹起來,引號須要用反斜槓\轉義)

6.3 mongodb類似度查詢

$meta操做符:{score:{$meta:'textScore'}}

查詢結果的類似度,搜索出的結果會多出一個score字段,這個得分越高,相關度越高。

db.article.find({$text:{$search:"aa bb ff"}},{score:{$meta:"textScore"}})

加上.sort方法可排序

db.article.find({$text:{$search:"aa bb ff"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})

6.4 全局索引的限制

  1. 每次查詢,只能指定一個$text查詢
  2. $text查詢不能出如今$nor查詢中
  3. 查詢中若是包含了$text, hint再也不起做用
  4. MongoDB全文索引還不支持中文

7.地理位置索引

  • 2d索引,用於存儲和查找平面上的點
  • 2dsphere索引,用於存儲和查找球面上的點

索引屬性

1.索引屬性name

MongoDB會自動的建立,規則是key_1 或者 key_-1 1或者-1表明排序方向,通常影響不大,長度通常有限制125字節
db.collection.ensureIndex({indexValue},{name: key})

爲了見名知意咱們能夠本身來命名

db.demo_3.ensureIndex({x:1,y:1,z:1,n:1},{name:'xyz-name'});

刪除索引

db.demo_3.dropIndex(indexName)

2. 索引屬性unique惟一性指定

相似關係型數據庫字段的惟一約束
db.demo_3.ensureIndex({m:1,n:1},{unique:true})

索引實例測試

創建500萬條數據,分別用來測試創建索引和未創建索引的差異,只有在大量數據下才有效果,如下的示例中的時間消耗值,各電腦配置的不一樣在不一樣電腦上測試也會有不一樣的差異。
  • 創建測試數據
> for(var i=0; i<5000000; i++) db.demo_user.insert({id: i})
WriteResult({ "nInserted" : 1 })
  • 未創建索引狀況數據查詢
在未創建索引的狀況下,執行數據查詢的時間消耗在6秒多。

圖片描述

  • 創建索引狀況查詢數據
db.getCollection('demo_user').ensureIndex({"id": 1}) # 創建索引

下圖爲創建索引的狀況,在數據查詢中僅用了0.001秒,可見創建索引的重要的性。

圖片描述

索引致使的庫級鎖

這是一個很坑爹的事情,MongoDB沒有像MySql、Oracle擁有行級粒度鎖概念,在MongoDB中只有庫級粒度鎖概念,意味這當你在生產環境中不當心觸發了一個寫鎖的操做時其它的業務也會受影響。

MongoDB中創建索引就是一個觸發寫鎖的過程,一般數據量越大創建的索引佔用的寫鎖時間就會越長,MongoDB中創建索引的兩種方式。

  • 前臺建立(錯誤)

    如下爲前臺創建索引演示能夠看到在執行建立索引命令以後,新打開一個終端查詢另外一張表一直處於等待狀態,直到建立索引完成才返回數據。

db.getCollection('demo_user').ensureIndex({"id": 1}) # 創建索引

圖片描述

  • 後臺建立(推薦)

基於後臺建立索引的方式在執行建立索引命令以後,新開一個終端查詢另外一個集合中的數據能夠當即獲得返回。

db.getCollection('demo_user').ensureIndex({"id": 1}, {background: 1}) # 創建索引

圖片描述

做者:五月君
連接:https://www.imooc.com/article...
來源:首發慕課網
Github: Node.js技術棧

推薦閱讀

相關文章
相關標籤/搜索