MongoDB性能優化

1、索引

MongoDB 提供了多樣性的索引支持,索引信息被保存在system.indexes 中,且默認老是爲_id建立索引,它的索引使用基本和MySQL 等關係型數據庫同樣。其實能夠這樣說說,索引是凌駕於數據存儲系統之上的另外一層系統,因此各類結構迥異的存儲都有相同或類似的索引實現及使用接口並不足爲 奇。數據庫

1.基礎索引

在字段age 上建立索引,1(升序);-1(降序):性能優化

db.users.ensureIndex({age:1})

_id 是建立表的時候自動建立的索引,此索引是不可以刪除的。當系統已有大量數據時,建立索引就是個很是耗時的活,咱們能夠在後臺執行,只需指定「backgroud:true」便可。app

db.t3.ensureIndex({age:1} , {backgroud:true})

2.文檔索引

索引能夠任何類型的字段,甚至文檔:ide

 
db.factories.insert( { name: "wwl", addr: { city: "Beijing", state: "BJ" } } );
//在addr 列上建立索引
db.factories.ensureIndex( { addr : 1 } );
//下面這個查詢將會用到咱們剛剛創建的索引
db.factories.find( { addr: { city: "Beijing", state: "BJ" } } );
//可是下面這個查詢將不會用到索引,由於查詢的順序跟索引創建的順序不同
db.factories.find( { addr: { state: "BJ" , city: "Beijing"} } );
 

3. 組合索引

跟其它數據庫產品同樣,MongoDB 也是有組合索引的,下面咱們將在addr.city 和addr.state上創建組合索引。當建立組合索引時,字段後面的1 表示升序,-1 表示降序,是用1 仍是用-1 主要是跟排序的時候或指定範圍內查詢 的時候有關的。工具

db.factories.ensureIndex( { "addr.city" : 1, "addr.state" : 1 } );
// 下面的查詢都用到了這個索引
db.factories.find( { "addr.city" : "Beijing", "addr.state" : "BJ" } );
db.factories.find( { "addr.city" : "Beijing" } );
db.factories.find().sort( { "addr.city" : 1, "addr.state" : 1 } );
db.factories.find().sort( { "addr.city" : 1 } )

4. 惟一索引

只需在ensureIndex 命令中指定」unique:true」便可建立惟一索引。例如,往表t4 中插入2 條記錄:性能

db.t4.ensureIndex({firstname: 1, lastname: 1}, {unique: true});

5.強制使用索引

hint 命令能夠強制使用某個索引。優化

db.t5.find({age:{$lt:30}}).hint({name:1, age:1}).explain()

6.刪除索引

//刪除t3 表中的全部索引
db.t3.dropIndexes()
//刪除t4 表中的firstname 索引
db.t4.dropIndex({firstname: 1})

2、explain執行計劃

MongoDB 提供了一個 explain 命令讓咱們獲知系統如何處理查詢請求。利用 explain 命令,咱們能夠很好地觀察系統如何使用索引來加快檢索,同時能夠針對性優化索引。日誌

 
  db.t5.ensureIndex({name:1})
  db.t5.ensureIndex({age:1})
  db.t5.find({age:{$gt:45}}, {name:1}).explain()
  {
      "cursor" : "BtreeCursor age_1",
      "nscanned" : 0,
      "nscannedObjects" : 0,
      "n" : 0,
      "millis" : 0,
      "nYields" : 0,
      "nChunkSkips" : 0,
      "isMultiKey" : false,
      "indexOnly" : false,
      "indexBounds" : {
      "age" : [
                    [45,1.7976931348623157e+308]
                ]
       }
}
 

字段說明:code

  • cursor: 返回遊標類型(BasicCursor 或 BtreeCursor)
  • nscanned: 被掃描的文檔數量
  • n: 返回的文檔數量
  • millis: 耗時(毫秒)
  • indexBounds: 所使用的索引

 

3、優化器profile

在MySQL 中,慢查詢日誌是常常做爲咱們優化數據庫的依據,那在MongoDB 中是否有相似的功能呢?答案是確定的,那就是MongoDB Database Profiler。server

1.開啓profiling功能

有兩種方式能夠控制 Profiling 的開關和級別,第一種是直接在啓動參數裏直接進行設置。啓動MongoDB 時加上–profile=級別 便可。也能夠在客戶端調用db.setProfilingLevel(級別) 命令來實時配置,Profiler 信息保存在system.profile 中。咱們能夠經過db.getProfilingLevel()命令來獲取當前的Profile 級別,相似以下操做:

db.setProfilingLevel(2);

上面profile 的級別能夠取0,1,2 三個值,他們表示的意義以下:

  1. 0 – 不開啓
  2. 1 – 記錄慢命令 (默認爲>100ms)
  3. 2 – 記錄全部命令

Profile 記錄在級別1 時會記錄慢命令,那麼這個慢的定義是什麼?上面咱們說到其默認爲100ms,固然有默認就有設置,其設置方法和級別同樣有兩種,一種是經過添加 –slowms 啓動參數配置。第二種是調用db.setProfilingLevel 時加上第二個參數:

db.setProfilingLevel( level , slowms )
db.setProfilingLevel( 1 , 10 );

2.查詢 Profiling 記錄

與MySQL 的慢查詢日誌不一樣,MongoDB Profile 記錄是直接存在系統db 裏的,記錄位置system.profile ,因此,咱們只要查詢這個Collection 的記錄就能夠獲取到咱們的 Profile 記錄了。列出執行時間長於某一限度(5ms)的 Profile 記錄:

db.system.profile.find( { millis : { $gt : 5 } } )

MongoDB Shell 還提供了一個比較簡潔的命令show profile,可列出最近5 條執行時間超過1ms 的 Profile 記錄。  

4、經常使用性能優化方案

  1. 建立索引
  2. 限定返回結果數
  3. 只查詢使用到的字段
  4. 採用capped collection
  5. 採用Server Side Code Execution
  6. 使用Hint,強制使用索引
  7. 採用Profiling

 

5、性能監控工具

1. mongosniff

此工具能夠從底層監控到底有哪些命令發送給了MongoDB 去執行,從中就能夠進行分析:以root 身份執行:

$./mongosniff --source NET lo

而後其會監控位到本地以localhost 監聽默認27017 端口的MongoDB 的全部包請求。

2.Mongostat

此工具能夠快速的查看某組運行中的MongoDB 實例的統計信息 字段說明:

  • insert: 每秒插入量
  • query: 每秒查詢量
  • update: 每秒更新量
  • delete: 每秒刪除量
  • locked: 鎖定量
  • qr | qw: 客戶端查詢排隊長度(讀|寫)
  • ar | aw: 活躍客戶端量(讀|寫)
  • conn: 鏈接數
  • time: 當前時間

它每秒鐘刷新一次狀態值,提供良好的可讀性,經過這些參數能夠觀察到一個總體的性能狀況。

3. db.serverStatus

這個命令是最經常使用也是最基礎的查看實例運行狀態的命令之一。

4.db.stats

相關文章
相關標籤/搜索