MongoDB效能最佳化及監控_MongoDB

來源:互聯網
上載者:User

MongoDB 是一個基於分布式檔案儲存體的資料庫。由 C++ 語言編寫。旨在為 WEB 應用提供可擴充的高效能資料儲存解決方案。

MongoDB 是一個介於關聯式資料庫和非關聯式資料庫之間的產品,是非關聯式資料庫當中功能最豐富,最像關聯式資料庫的。

一、索引

MongoDB 提供了多樣性的索引支援,索引資訊被儲存在system.indexes 中,且預設總是為_id建立索引,它的索引使用基本和MySQL 等關係型資料庫一樣。其實可以這樣說說,索引是淩駕於資料存放區系統之上的另一層系統,所以各種結構迥異的儲存都有相同或相似的索引實現及使用介面並不足為 奇。

1.基礎索引

在欄位age 上建立索引,1(升序);-1(降序):

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

_id 是建立表的時候自動建立的索引,此索引是不能夠刪除的。當系統已有大量資料時,建立索引就是個非常耗時的活,我們可以在後台執行,只需指定“backgroud:true”即可。

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

2.文檔索引

索引可以任何類型的欄位,甚至文檔:

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}) 

二、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]]}} 

欄位說明:

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

三、最佳化器profile

在MySQL 中,慢查詢日誌是經常作為我們最佳化資料庫的依據,那在MongoDB 中是否有類似的功能呢?答案是肯定的,那就是MongoDB Database Profiler。

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 記錄。

四、常用效能最佳化方案

1.建立索引

2.限定返回結果數

3.只查詢使用到的欄位

4.採用capped collection

5.採用Server Side Code Execution

6.使用Hint,強制使用索引

7.採用Profiling

五、效能監控工具

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

下面給大家介紹下mongodb的監控

mongodb可以通過profile來監控資料,進行最佳化。

查看當前是否開啟profile功能用命令

db.getProfilingLevel() 返回level等級,值為0|1|2,分別代表意思:0代表關閉,1代表記錄慢命令,2代表全部開始profile功能為

db.setProfilingLevel(level); #level等級,值同上level為1的時候,慢命令預設值為100ms,更改為db.setProfilingLevel(level,slowms)如db.setProfilingLevel(1,50)這樣就更改為50毫秒通過db.system.profile.find() 查看當前的監控日誌。
如:

> db.system.profile.find({millis:{$gt:500}}) { "ts" : ISODate("2011-07-23T02:50:13.941Z"), "info" : "query order.order reslen:11022 nscanned:672230 \nquery: { status: 1.0 } nreturned:101 bytes:11006 640ms", "millis" : 640 } { "ts" : ISODate("2011-07-23T02:51:00.096Z"), "info" : "query order.order reslen:11146 nscanned:672302 \nquery: { status: 1.0, user.uid: { $gt: 1663199.0 } } nreturned:101 bytes:11130 647ms", "millis" : 647 } 

這裡值的含義是

ts:命令執行時間
info:命令的內容
query:代表查詢
order.order: 代表查詢的庫與集合
reslen:返回的結果集大小,byte數
nscanned:掃描記錄數量
nquery:後面是查詢條件
nreturned:返回記錄數及用時
millis:所花時間

如果發現時間比較長,那麼就需要作最佳化。

比如nscanned數很大,或者接近記錄總數,那麼可能沒有用到索引查詢。
reslen很大,有可能返回沒必要的欄位。
nreturned很大,那麼有可能查詢的時候沒有加限制。

mongo可以通過db.serverStatus()查看mongod的運行狀態

> db.serverStatus() { "host" : "baobao-laptop",#主機名稱 "version" : "1.8.2",#版本號碼 "process" : "mongod",#進程名 "uptime" : 15549,#已耗用時間 "uptimeEstimate" : 15351, "localTime" : ISODate("2011-07-23T06:07:31.220Z"),目前時間 "globalLock" : { "totalTime" : 15548525410,#總已耗用時間(ns) "lockTime" : 89206633, #總的鎖時間(ns) "ratio" : 0.005737305027178137,#鎖比值 "currentQueue" : { "total" : 0,#當前需要執行的隊列 "readers" : 0,#讀隊列 "writers" : 0#寫隊列 }, "activeClients" : { "total" : 0,#當前用戶端執行的連結數 "readers" : 0,#讀連結數 "writers" : 0#寫連結數 } }, "mem" : {#記憶體情況 "bits" : 32,#32位系統 "resident" : 337,#佔有實體記憶體數 "virtual" : 599,#佔有虛擬記憶體 "supported" : true,#是否支援擴充記憶體 "mapped" : 512 }, "connections" : { "current" : 2,#當前連結數 "available" : 817#可用連結數 }, "extra_info" : { "note" : "fields vary by platform", "heap_usage_bytes" : 159008,#堆使用方式位元組 "page_faults" : 907 #頁面故作 }, "indexCounters" : { "btree" : { "accesses" : 59963, #索引被訪問數 "hits" : 59963, #所以命中數 "misses" : 0,#索引偏差數 "resets" : 0,#複位元 "missRatio" : 0#未命中率 } }, "backgroundFlushing" : { "flushes" : 259, #重新整理次數 "total_ms" : 3395, #重新整理總花費時間長度 "average_ms" : 13.108108108108109, #平均時間長度 "last_ms" : 1, #最後一次時間長度 "last_finished" : ISODate("2011-07-23T06:07:22.725Z")#最後重新整理時間 }, "cursors" : { "totalOpen" : 0,#開啟遊標數 "clientCursors_size" : 0,#用戶端資料指標大小 "timedOut" : 16#逾時時間 }, "network" : { "bytesIn" : 285676177,#輸入資料(byte) "bytesOut" : 286564,#輸出資料(byte) "numRequests" : 2012348#請求數 }, "opcounters" : { "insert" : 2010000, #插入運算元 "query" : 51,#查詢運算元 "update" : 5,#更新運算元 "delete" : 0,#刪除運算元 "getmore" : 0,#擷取更多的運算元 "command" : 148#其他命令運算元 }, "asserts" : {#各個斷言的數量 "regular" : 0, "warning" : 0, "msg" : 0, "user" : 2131, "rollovers" : 0 }, "writeBacksQueued" : false, "ok" : 1 } db.stats()查看某一個庫的原先狀況> db.stats() { "db" : "order",#庫名 "collections" : 4,#集合數 "objects" : 2011622,#記錄數 "avgObjSize" : 111.92214441878245,#每條記錄的平均值 "dataSize" : 225145048,#記錄的總大小 "storageSize" : 307323392,#預分配的儲存空間 "numExtents" : 21,#事件數目 "indexes" : 1,#索引數 "indexSize" : 74187744,#所以大小 "fileSize" : 1056702464,#檔案大小 "ok" : 1 } 

查看集合記錄用

> db.order.stats() { "ns" : "order.order",#命名空間 "count" : 2010000,#記錄數 "size" : 225039600,#大小 "avgObjSize" : 111.96, "storageSize" : 307186944, "numExtents" : 18, "nindexes" : 1, "lastExtentSize" : 56089856, "paddingFactor" : 1, "flags" : 1, "totalIndexSize" : 74187744, "indexSizes" : { "_id_" : 74187744#索引為_id_的索引大小 }, "ok" : 1 }

mongostat命令查看運行中的即時統計,表示每秒即時執行的次數

mongodb還提供了一個機遇http的監控頁面,可以訪問http://ip:28017來查看,這個頁面基本上是對上面的這些命令做了一下綜合,所以這裡不細述了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.