摘要:mongodb
在MySQL中,慢查詢日誌是常常做爲咱們優化查詢的依據,那在MongoDB中是否有相似的功能呢?答案是確定的,那就是開啓Profiling功能。該工具在運行的實例上收集有關MongoDB的寫操做,遊標,數據庫命令等,能夠在數據庫級別開啓該工具,也能夠在實例級別開啓。該工具會把收集到的全部都寫入到system.profile集合中,該集合是一個capped collection。更多的信息見:http://docs.mongodb.org/manual/tutorial/manage-the-database-profiler/和http://mp.weixin.qq.com/s?__biz=MzA4Nzg5Nzc5OA==&mid=207007436&idx=1&sn=a63601d81c8d112228c96ad9fffb031c&scene=21#wechat_redirect
shell
使用說明:數據庫
1:Profiling級別說明app
0:關閉,不收集任何數據。 1:收集慢查詢數據,默認是100毫秒。 2:收集全部數據
2:開啓Profiling和設置工具
1:經過mongo shell: #查看狀態:級別和時間 drug:PRIMARY> db.getProfilingStatus() { "was" : 1, "slowms" : 100 } #查看級別 drug:PRIMARY> db.getProfilingLevel() 1 #設置級別 drug:PRIMARY> db.setProfilingLevel(2) { "was" : 1, "slowms" : 100, "ok" : 1 } #設置級別和時間 drug:PRIMARY> db.setProfilingLevel(1,200) { "was" : 2, "slowms" : 100, "ok" : 1 } 以上要操做要是在test集合下面的話,只對該集合裏的操做有效,要是須要對整個實例有效,則須要在全部的集合下設置或則在開啓的時候開啓參數: 2:不經過mongo shell: mongod --profile=1 --slowms=15 或則在配置文件裏添加2行: profile = 1 slowms = 300
3:關閉Profiling性能
# 關閉 drug:PRIMARY> db.setProfilingLevel(0) { "was" : 1, "slowms" : 200, "ok" : 1 }
4:修改「慢查詢日誌」的大小優化
#關閉Profiling drug:PRIMARY> db.setProfilingLevel(0) { "was" : 0, "slowms" : 200, "ok" : 1 } #刪除system.profile集合 drug:PRIMARY> db.system.profile.drop() true #建立一個新的system.profile集合 drug:PRIMARY> db.createCollection( "system.profile", { capped: true, size:4000000 } ) { "ok" : 1 } #從新開啓Profiling drug:PRIMARY> db.setProfilingLevel(1) { "was" : 0, "slowms" : 200, "ok" : 1 }
注意:要改變Secondary的system.profile的大小,你必須中止Secondary,運行它做爲一個獨立的,而後再執行上述步驟。完成後,從新啓動加入副本集。ui
慢查詢(system.profile)說明:this
經過下面的例子說明,更多信息見:http://docs.mongodb.org/manual/reference/database-profiler/spa
1:參數含義
drug:PRIMARY> db.system.profile.find().pretty() { "op" : "query", #操做類型,有insert、query、update、remove、getmore、command "ns" : "mc.user", #操做的集合 "query" : { #查詢語句 "mp_id" : 5, "is_fans" : 1, "latestTime" : { "$ne" : 0 }, "latestMsgId" : { "$gt" : 0 }, "$where" : "new Date(this.latestNormalTime)>new Date(this.replyTime)" }, "cursorid" : NumberLong("1475423943124458998"), "ntoreturn" : 0, #返回的記錄數。例如,profile命令將返回一個文檔(一個結果文件),所以ntoreturn值將爲1。limit(5)命令將返回五個文件,所以ntoreturn值是5。若是ntoreturn值爲0,則該命令沒有指定一些文件返回,由於會是這樣一個簡單的find()命令沒有指定的限制。 "ntoskip" : 0, #skip()方法指定的跳躍數 "nscanned" : 304, #掃描數量 "keyUpdates" : 0, #索引更新的數量,改變一個索引鍵帶有一個小的性能開銷,由於數據庫必須刪除舊的key,並插入一個新的key到B-樹索引 "numYield" : 0, #該查詢爲其餘查詢讓出鎖的次數 "lockStats" : { #鎖信息,R:全局讀鎖;W:全局寫鎖;r:特定數據庫的讀鎖;w:特定數據庫的寫鎖 "timeLockedMicros" : { #鎖 "r" : NumberLong(19467), "w" : NumberLong(0) }, "timeAcquiringMicros" : { #鎖等待 "r" : NumberLong(7), "w" : NumberLong(9) } }, "nreturned" : 101, #返回的數量 "responseLength" : 74659, #響應字節長度 "millis" : 19, #消耗的時間(毫秒) "ts" : ISODate("2014-02-25T02:13:54.899Z"), #語句執行的時間 "client" : "127.0.0.1", #連接ip或則主機 "allUsers" : [ ], "user" : "" #用戶 }
除上面外還有:
scanAndOrder: scanAndOrder是一個布爾值,是True當一個查詢不能使用的文件的順序在索引中的排序返回結果:MongoDB中必須將其接收到的文件從一個遊標後的文件進行排序。 若是scanAndOrder是False,MongoDB的可以使用這些文件的順序索引返回排序的結果。即:True:文檔進行排序,False:使用索引。 moved 更新操做在磁盤上移動一個或多個文件到新的位置。代表本次update是否移動了硬盤上的數據,若是新記錄比原記錄短,一般不會移動當前記錄,若是新記錄比原記錄長,那麼可能會移動記錄到其它位置,這時候會致使相關索引的更新.磁盤操做更多,加上索引
更新,會使得這樣的操做比較慢. nmoved: 文件在磁盤上操做。 nupdated: 更新文檔的數目
getmore是一個getmore 操做,getmore一般發生在結果集比較大的查詢時,第一個query返回了部分結果,後續的結果是經過getmore來獲取的。
若是nscanned(掃描的記錄數)遠大於nreturned(返回結果的記錄數)的話,要考慮經過加索引來優化記錄定位了。responseLength 若是過大,說明返回的結果集太大了,這時要看是否只須要必要的字段。
2:平常使用的查詢
#返回最近的10條記錄 db.system.profile.find().limit(10).sort({ ts : -1 }).pretty() #返回全部的操做,除command類型的 db.system.profile.find( { op: { $ne : 'command' } } ).pretty() #返回特定集合 db.system.profile.find( { ns : 'mydb.test' } ).pretty() #返回大於5毫秒慢的操做 db.system.profile.find( { millis : { $gt : 5 } } ).pretty() #從一個特定的時間範圍內返回信息 db.system.profile.find( { ts : { $gt : new ISODate("2012-12-09T03:00:00Z") , $lt : new ISODate("2012-12-09T03:40:00Z") } } ).pretty() #特定時間,限制用戶,按照消耗時間排序 db.system.profile.find( { ts : { $gt : new ISODate("2011-07-12T03:00:00Z") , $lt : new ISODate("2011-07-12T03:40:00Z") } }, { user : 0 } ).sort( { millis : -1 } )
總結:
Profiling 功能確定是會影響效率的,可是不太嚴重,緣由是他使用的是system.profile 來記錄,而system.profile 是一個capped collection 這種collection 在操做上有一些限制和特色,可是效率更高,因此在使用的時候能夠打開該功能,不須要一直打開。