1. 程式人生 > >Mongodb效能調優 -效能優化建議

Mongodb效能調優 -效能優化建議

摘要
1. MongoDB 適用場景簡介
2. Mongodb 效能監控與分析
3. Mongodb 效能優化建議

關於Mongodb的幾個大事件
1.根據美國資料庫知識大全官網釋出的DB熱度排行,Mongodb的熱度排名從2014年的第5名,在2015年躍升為第4名,僅次於主流DB(OracleMySQL、SQLServer)之後。

這裡寫圖片描述

2.2015第六屆中國資料庫技術大會(DTCC)上,Mongodb高調宣佈收購開源引擎WiredTiger,效能在3.0版本上實現了7~10倍的提升。

Mongodb 適用場景簡介

適用場景
1. 實時的CRU操作,如網站、論壇等實時資料儲存
2. 高伸縮性,可以分散式叢集,動態增刪節點
3. 儲存大尺寸、低價值資料
4. 快取
5. BSON結構物件儲存
不適用場景
1. 高度事務性操作,如銀行或會計系統
2. 傳統商業智慧應用,如提供高度優化的查詢方式
3. 需要SQL的問題
4. 重要資料,關係型資料

Mongodb 效能監控與分析

mongostat
1. faults/s:每秒訪問失敗數,即資料被交換出實體記憶體,放到SWAP。
若過高(一般超過100),則意味著記憶體不足。
vmstat & iostat & iotop
這裡寫圖片描述
si:每秒從磁碟讀入虛擬記憶體的大小,若大於0,表示實體記憶體不足。
so:每秒虛擬記憶體寫入磁碟的大小,若大於0,同上。

mongostat
2. idx miss %:BTree 樹未命中的比例,即索引不命中所佔百分比。
若過高,則意味著索引建立或使用不合理。
db.serverStatus()
indexCounters” : {
“btree” : {
“accesses” : 2821726, #索引被訪問數
“hits” : 2821725, #索引命中數
“misses” : 1, #索引偏差數
“resets” : 0, #復位數
“missRatio” : 3.543930204420982e-7 #未命中率
}

mongostat
3. locked %:全域性寫入鎖佔用了機器多少時間。當發生全域性寫入鎖時,所有查詢操作都將等待,直到寫入鎖解除。
若過高(一般超過50%),則意味著程式存在問題。
db.currentOp()
{
“inprog” : [ ],
“fsyncLock” : 1, #為1表示MongoDB的fsync程序(負責將寫入改變同步到磁碟)不允許其他程序執行寫資料操作
“info” : “use db.fsyncUnlock() to terminate the fsync write/snapshot lock”
}

mongostat
4. q r|w :等待處理的查詢請求佇列大小。
若過高,則意味著查詢會過慢。
db.serverStatus()
“currentQueue” : {
“total” : 1024, #當前需要執行的佇列
“readers” : 256, #讀佇列
“writers” : 768 #寫佇列
}

mongostat
5. conn :當前連線數。
高併發下,若連線數上不去,則意味著Linux系統核心需要調優。
db.serverStatus()
“connections” : {
“current” : 3, #當前連線數
“available” : 19997 #可用連線數
}

6.連線數使用記憶體過大

shell> cat /proc/$(pidof mongod)/limits | grep stack | awk -F 'size' '{print int($NF)/1024}'
  • 1
  • 1

將連線數使用Linux棧記憶體設小,預設為10MB(10240)

shell> ulimit -s 1024

優化器Profile
db.setProfilingLevel(2);
0 – 不開啟
1 – 記錄慢命令 (預設為>100ms)
2 – 記錄所有命令
info: #本命令的詳細資訊
reslen: #返回結果集的大小
nscanned: #本次查詢掃描的記錄數
nreturned: #本次查詢實際返回的結果集
millis: #該命令執行耗時(毫秒)

這裡寫圖片描述

  1. 表KnowledgeAnswer未建立有效索引(建議考慮使用組合索引)
  2. 存在大量慢查詢,均為表KnowledgeAnswer讀操作,且響應超過1秒
  3. 每次讀操作均為全表掃描,意味著耗用CPU(25% * 8核)
  4. 每次返回的記錄位元組數近1KB,建議過濾不必要的欄位,提高傳輸效率

執行計劃Explain
db.test.find({age: “20”}).hint({age:1 }).explain();
cursor: 返回遊標型別(BasicCursor 或 BtreeCursor)
nscanned: 被掃描的文件數量
n: 返回的文件數量
millis: 耗時(毫秒)
indexBounds: 所使用的索引

這裡寫圖片描述

這裡寫圖片描述

  1. 在查詢條件、排序條件、統計條件的欄位上選擇建立索引
    db.student.ensureIndex({name:1,age:1} , {backgroud:true});
    注意:
     最新或最近記錄查詢,結合業務需要正確使用索引方向:逆序或順序
     建議索引建立操作置於後臺執行,降低影響
     實際應用過程中多考慮使用複合索引
     使用limit()限定返回結果集的大小,減少資料庫伺服器的資源消耗,以及網路傳輸的資料量
    db.posts.find().sort({ts:-1}).limit(10);
  2. 只查詢使用到的欄位,而不查詢所有欄位
    db.posts.find({ts:1,title:1,author:1,abstract:1}).sort({ts:-1}).limit(10);

  3. 基於Mongodb分散式叢集做資料分析時,MapReduce效能優於count、distinct、group等聚合函式

    這裡寫圖片描述

  4. Capped Collections比普通Collections的讀寫效率高
    db.createCollection(“mycoll”, {capped:true, size:100000});
    例:system.profile 是一個Capped Collection。
    注意:
     固定大小;Capped Collections 必須事先建立,並設定大小。
     Capped Collections可以insert和update操作;不能delete操作。只能用 drop()方法刪除整個Collection。
     預設基於 Insert 的次序排序的。如果查詢時沒有排序,則總是按照insert的順序返回。
     FIFO。如果超過了Collection的限定大小,則用 FIFO 演算法,新記錄將替代最先 insert的記錄。

  5. Mongodb 3.0.X版本效能較Mongodb 2.0.X有7-10倍提升,引入WiredTiger新引擎,同時支援MMAPv1記憶體對映引擎

這裡寫圖片描述

注意:
 預設MMAPv1,切換至WiredTiger:mongod –dbpath /usr/local/mongodb/data –storageEngine wiredTiger
備註:若更換新引擎,則之前使用舊引擎建立的DB資料庫無法使用。 建議先通過Mongodb的同步機制,將舊引擎建立的DB資料同步到從庫, 且從庫使用新引擎.
 選擇 Windows 2008 R2 x64 或 Linux x64,Linux版本效能優於 Windows,建議基於Linux系統進行架構選型
 根據RHEL版本號選擇Mongodb相應Linux版本
 Mongodb Driver 與 Mongodb 版本一致

最後的建議
哪一種物理設計更適合Mongodb:正規化化 & 反正規化化 & 業務 ?
 正規化化設計的思想是“完全分離”,存在關聯查詢,查詢效率低,但寫入、修改、刪除效能更高
 反正規化化設計的思想是“資料集中儲存”,查詢效率高,而Mongodb對查詢機制支援較弱,看似成為一種互補

下面我們來看一個圖書資訊DB表設計案例:

示例1:正規化化設計

{
     "_id" : ObjectId("5124b5d86041c7dca81917"),
     "title" : "MongoDB效能調優", 
      "author" : [ 
               ObjectId("144b5d83041c7dca84416"),
              ObjectId("144b5d83041c7dca84418"),
              ObjectId("144b5d83041c7dca84420"),
     ]
 } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

分析:更新效率高,因為不需要關聯表操作。比如更新作者年齡,只需要更新作者資訊1張表就可以了。而查詢效率低,因為需要關聯表操作。比如檢視某本圖書的作者簡介,需要先查圖書資訊表以獲取作者ID,再根據ID,在作者資訊表中查詢作者簡介資訊。

示例2:反正規化化設計

{
       "_id" : ObjectId("5124b5d86041c7dca81917"),
       "title" : "MongoDB效能調優",
       "author" : [
                {
                         "name" : "張三"
                         "age" : 40,
                         "nationality" : "china",
                },
                {
                         "name" : "李四"
                         "age" : 49,
                         "nationality" : "china",
                },
                {
                         "name" : "王五"
                         "age" : 59,
                         "nationality" : "china",
                },
      ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

分析:將作者簡介資訊嵌入到圖書資訊表中,這樣查詢效率高,不需要關聯表操作。依然是更新作者年齡,此時更新效率就顯得低,因為該作者出過多本書,需要修改多本圖書資訊記錄中該作者的年齡。

示例3:不完全正規化化設計

{
       "_id" : ObjectId("5124b5d86041c7dca81917"),
       "title" : "MongoDB效能調優",
       "author" : [ 
               {
                         "_id" : ObjectId("144b5d83041c7dca84416"),
                         "name" : "張三"
                },
                {
                         "_id" : ObjectId("144b5d83041c7dca84418"),
                         "name" : "李四"
                },
                {
                         "_id" : ObjectId("144b5d83041c7dca84420"),
                         "name" : "王五"
                },
      ]
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

分析:其實我們知道某本書的作者姓名是不會變化的,屬於靜態資料,又比如作者的年齡、收入、關注度等,均屬於動態資料,所以結合業務特點,圖書資訊表肯定是查詢頻率高、修改頻率低,故可以將一些作者的靜態資料嵌入到圖書資訊表中,做一個折中處理,這樣效能更優。

總結:Mongodb效能調優不是最終或最有效的手段,最高效的方法是做出好的物理設計。而什麼樣的物理設計適合Mongodb,最後還是由當前業務及業務未來發展趨勢決定的。最後送給大家一句話“好的效能不是調出來的,更多是設計出來的”!