1. 程式人生 > >Mongodb 3 查詢優化

Mongodb 3 查詢優化

user 開啟 情況下 can 數量 還得 min 類型 數據

開啟慢查詢Profiling

Profiling級別說明

0:關閉,不收集任何數據。
1:收集慢查詢數據,默認是100毫秒。
2:收集所有數據

1、通過修改配置文件開啟Profiling

  修改啟動mongo.conf,插入以下代碼

#開啟慢查詢,200毫秒的記錄
profile = 1
slowms = 200

2、在啟動mongodb服務以後,通過mongoshell來進行臨時性打開啟,只要關閉了mongodb服務,下次開啟就不會啟動,還得再開一次

(1)、在mongodb有權限的情況下,通過命令登錄,如果沒有權限可以不用寫--username後面的內容

mongo --host 127.0.0.1:27017 --username 你的用戶名 --password 你的密碼 --authenticationDatabase admin

(2)、跳轉到要開啟慢查詢監控的數據庫

use test

(3)、設置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 }

(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,運行它作為一個獨立的,然後再執行上述步驟。完成後,重新啟動加入副本集。

慢查詢(system.profile)說明:

通過下面的例子說明,更多信息見:http://docs.mongodb.org/manual/reference/database-profiler/

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

Mongodb 3 查詢優化