mongodb 性能調優建議

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

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

這裏寫圖片描述

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

Mongodb 適用場景簡介算法

適用場景 
1. 實時的CRU操做,如網站、論壇等實時數據存儲 
2. 高伸縮性,能夠分佈式集羣,動態增刪節點 
3. 存儲大尺寸、低價值數據 
4. 緩存 
5. BSON結構對象存儲 
不適用場景 
1. 高度事務性操做,如銀行或會計系統 
2. 傳統商業智能應用,如提供高度優化的查詢方式 
3. 須要SQL的問題 
4. 重要數據,關係型數據sql

Mongodb 性能監控與分析mongodb

mongostat 
1. faults/s:每秒訪問失敗數,即數據被交換出物理內存,放到SWAP。 
若太高(通常超過100),則意味着內存不足。 
vmstat & iostat & iotop 
這裏寫圖片描述
si:每秒從磁盤讀入虛擬內存的大小,若大於0,表示物理內存不足。 
so:每秒虛擬內存寫入磁盤的大小,若大於0,同上。shell

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
  • 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:範式化設計

 
  1. {

  2. "_id" : ObjectId("5124b5d86041c7dca81917"),

  3. "title" : "MongoDB性能調優",

  4. "author" : [

  5. ObjectId("144b5d83041c7dca84416"),

  6. ObjectId("144b5d83041c7dca84418"),

  7. ObjectId("144b5d83041c7dca84420"),

  8. ]

  9. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

分析:更新效率高,由於不須要關聯表操做。好比更新做者年齡,只須要更新做者信息1張表就能夠了。而查詢效率低,由於須要關聯表操做。好比查看某本圖書的做者簡介,須要先查圖書信息表以獲取做者ID,再根據ID,在做者信息表中查詢做者簡介信息。

示例2:反範式化設計

 
  1. {

  2. "_id" : ObjectId("5124b5d86041c7dca81917"),

  3. "title" : "MongoDB性能調優",

  4. "author" : [

  5. {

  6.      "name" : "張三"

  7.      "age" : 40,

  8.     "nationality" : "china",

  9. },

  10. {

  11.      "name" : "李四"

  12.      "age" : 49,

  13.      "nationality" : "china",

  14. },

  15. {

  16.      "name" : "王五"

  17.      "age" : 59,

  18.      "nationality" : "china",

  19. },

  20. ]

  21. }

  • 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

示例3:不徹底範式化設計

 
  1. {

  2. "_id" : ObjectId("5124b5d86041c7dca81917"),

  3. "title" : "MongoDB性能調優",

  4. "author" : [

  5. {

  6.     "_id" : ObjectId("144b5d83041c7dca84416"),

  7.      "name" : "張三"

  8. },

  9. {

  10.      "_id" : ObjectId("144b5d83041c7dca84418"),

  11.      "name" : "李四"

  12. },

  13. {

  14.      "_id" : ObjectId("144b5d83041c7dca84420"),

  15.      "name" : "王五"

  16. },

  17. ]

  18. }

  • 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

分析:其實咱們知道某本書的做者姓名是不會變化的,屬於靜態數據,又好比做者的年齡、收入、關注度等,均屬於動態數據,因此結合業務特色,圖書信息表確定是查詢頻率高、修改頻率低,故能夠將一些做者的靜態數據嵌入到圖書信息表中,作一個折中處理,這樣性能更優。

總結:Mongodb性能調優不是最終或最有效的手段,最高效的方法是作出好的物理設計。而什麼樣的物理設計適合Mongodb,最後仍是由當前業務及業務將來發展趨勢決定的。最後送給你們一句話「好的性能不是調出來的,更可能是設計出來的」!

相關文章
相關標籤/搜索