一塊兒飛系列之:淺談Mongodb的索引優化

難度水平:初中級
適用人羣:對Mongodb數據查詢已經必定經驗的碼農,瞭解explain()的用法。
閱讀時間:10分鐘

緣起

原本是打算回答一個網友的問題,不過回覆框過小並且功能不全(差評^o^),因而乎就成就了本文的產生。在這裏我主要就是想跟你們分享一下我對Mongodb索引的粗淺理解,拋磚引玉,但願能對一些人有所幫助。數據庫

對於數據庫的索引相信你們都不陌生,主要功能就是在數據庫內提升針對特定信息的訪問速度。那麼在Mongodb裏面索引是怎樣被引用跟查找的呢?下面我來經過幾個例子給你們分享一下個人心得體會。函數

Mongodb基礎數據查詢

舉個栗子,按照城市查詢車牌號碼系統。爲了方便演示,我在全部查詢後面都加入了explain()函數。要注意explain的返回結果集中的一下選項:優化

  • cursor - 索引項
  • n - 查詢結果的條目總數
  • nscanned - 掃描並讀取的索引條目數(index)
  • nscannedObjects - 掃描並讀取的全文條目數(documents)
  • indexOnly - 是否使用了covered indexes功能,寶寶不哭,後面有詳述。
  • millis - 查詢用時,單位是毫秒。

栗子1: 在沒有索引的狀況下查詢所有北京車牌號碼

db.carLicence.find({city:'Beijing'}).explain()

//返回結果以下:
{
  "cursor" : "BasicCursor",
  "n" : 1563247,
  "nscannedObjects" : 96539732,
  "nscanned" : 96539732,
  "indexOnly" : false,
  "millis" : 156, // 哭!
}

BasicCursor表示全文檢索。上面的例子說明,在沒有索引的狀況下,該查詢語句查詢了整個數據集carLicence。該數據集包含了96539732數據,其中1563247屬於北京車牌。整個用時爲156毫秒.code

小結: 必定要避免沒有索引的全文查詢索引


栗子2: 在沒有索引的狀況下,使用limit(1000)來查詢北京車牌號碼

db.carLicence.find({city:'Beijing'}).limit(1000).explain()

//返回結果以下:
{
  "cursor" : "BasicCursor",
  "n" : 1000,
  "nscannedObjects" : 18476396,
  "nscanned" : 18476396,
  "indexOnly" : false,
  "millis" : 85, // 擦乾眼淚!
}

這個例子說明,Mongodb在搜索滿1000個條目以後就中止繼續檢索了。ci

小結: 儘可能使用limit()來處理你的數據查詢文檔


栗子3: 添加索引

由於咱們只是須要獲得北京市的車牌號碼,因此在咱們的例子中涉及到了2個索引信息,一個是城市city,另一個就是車牌號碼licence。那麼咱們來給這2個信息添加索引,來查詢所有北京車牌號碼。hash

注意:給2個以上的字段創建索引叫作Compound Index複合索引[多字段索引),hashed字段不能建立索引。創建方法以下db.carLicence.ensureIndex( { "city": 1, "licence": 1 } )
db.carLicence.find({city:'Beijing'}).explain()

//返回結果以下:
{
  "cursor" : "BasicCursor city_1_licence_1",
  "n" : 1563247,
  "nscannedObjects" : 1563247,
  "nscanned" : 1563247,
  "indexOnly" : false,
  "millis" : 47, // 只剩 擦!
}

相信看到這裏,你們已經對全部的功效有了一個初步的認識了。it

小結 - 儘可能給涉及到的條目創建索引基礎

那麼,indexOnly的covered indexes功能會有什麼樣的提升呢?好讓咱們來看最後這個例子。


栗子4: 使用覆蓋索引 Covered Indexes

db.carLicence.find({city:'Beijing'}, {licence:1, _id:0}).explain()

//返回結果以下:
{
  "cursor" : "BasicCursor city_1_licence_1",
  "n" : 1563247,
  "nscannedObjects" : 0,
  "nscanned" : 1563247,
  "indexOnly" : true, // 變了 變了 !
  "millis" : 41, // 擦!擦!擦!
}

最後這個例子涉及到了covered indexes(覆蓋索引),一般來講,覆蓋索引只在查詢文檔的索引字段時候使用。可是有幾個特性跟附加條件要遵循.

  • 查詢字段必須是索引字段
  • 要去掉_id由於是返回的Object. 經過_id:0來實現。
  • 索引字段不能是. 也就是說在explain()裏面,若是isMultiKey:true的話indexOnly必定是false.

另一個就是在最後一個栗子裏面nscannedObjects是零,這是由於咱們只是提取了索引裏面的目錄條licence,並不須要每一條的所有數據(document),加上"indexOnly" : true,因此, Mongodb直接從索引裏面提取了數據licence,不用再去查詢物理數據集carLicence獲得相關全文信息。因此nscannedObjects爲零。

小結 - 在只提單字段數據的前提下,要給對應的但字段創建索引索引

結語

粗淺的分析一下我對索引的理解跟一些優化體驗。有興趣的朋友能夠共通研究。最後說一句,善用explain()能對你的優化查詢有很大的益處。加油!

相關文章
相關標籤/搜索