2015/12/7

如何在 MongoDB 處理最佳化的問題

MongoDB 有許多查詢的機制,但需要搭配使用一些工具,了解怎麼讓查詢的效能最佳化。

索引

MongoDB 可針對所有文件類型建立索引,但查詢時是否有用到索引的條件是根據索引建立的順序來決定的。

針對 age 欄位建立索引

> db.mate.ensureIndex({age:1});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

取得 collection 所有 indexes

> db.mate.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.mate"
    },
    {
        "v" : 1,
        "key" : {
            "age" : 1
        },
        "name" : "age_1",
        "ns" : "test.mate"
    }
]

建立複合索引

> db.mate.ensureIndex({age:1, room:1});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 2,
    "numIndexesAfter" : 3,
    "ok" : 1
}

> db.mate.find().sort( {age:1, room:1});
{ "_id" : ObjectId("5641980c997bc79c93b12e7a"), "userid" : "danny", "username" : "Danny Huang", "city" : "Taipei" }
{ "_id" : ObjectId("5641980c997bc79c93b12e7b"), "userid" : "johnny", "username" : "Johnny Lo", "city" : "Taipei", "age" : null }
{ "_id" : ObjectId("5641980c997bc79c93b12e76"), "userid" : "muder", "username" : "Muder Yen", "city" : "Taichung", "age" : 19, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e75"), "userid" : "john", "username" : "John Lin", "city" : "Taipei", "age" : 20, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e78"), "userid" : "celina", "username" : "Celina Lin", "city" : "Taichung", "age" : 20, "room" : "601" }
{ "_id" : ObjectId("5641980c997bc79c93b12e79"), "userid" : "lunar", "username" : "Lunar Wang", "city" : "I Lan", "age" : 22, "room" : "302" }
{ "_id" : ObjectId("5641980c997bc79c93b12e77"), "userid" : "mary", "username" : "Mary Wang", "city" : "Tainan", "age" : 23, "room" : "601" }
> db.mate.find().sort( {age:-1, room:1});
{ "_id" : ObjectId("5641980c997bc79c93b12e77"), "userid" : "mary", "username" : "Mary Wang", "city" : "Tainan", "age" : 23, "room" : "601" }
{ "_id" : ObjectId("5641980c997bc79c93b12e79"), "userid" : "lunar", "username" : "Lunar Wang", "city" : "I Lan", "age" : 22, "room" : "302" }
{ "_id" : ObjectId("5641980c997bc79c93b12e75"), "userid" : "john", "username" : "John Lin", "city" : "Taipei", "age" : 20, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e78"), "userid" : "celina", "username" : "Celina Lin", "city" : "Taichung", "age" : 20, "room" : "601" }
{ "_id" : ObjectId("5641980c997bc79c93b12e76"), "userid" : "muder", "username" : "Muder Yen", "city" : "Taichung", "age" : 19, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e7a"), "userid" : "danny", "username" : "Danny Huang", "city" : "Taipei" }
{ "_id" : ObjectId("5641980c997bc79c93b12e7b"), "userid" : "johnny", "username" : "Johnny Lo", "city" : "Taipei", "age" : null }

刪除所有索引,除了 _id 無法刪除之外

> db.mate.dropIndexes();
{
    "nIndexesWas" : 3,
    "msg" : "non-_id indexes dropped for collection",
    "ok" : 1
}

以 unique 指定該索引值必須要是 唯一的,不能有重複的紀錄

> db.mate.ensureIndex({userid:1}, {unique:true});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> db.mate.ensureIndex({age:1}, {unique:true});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 2,
    "errmsg" : "exception: E11000 duplicate key error index: test.mate.$age_1 dup key: { : null }",
    "code" : 11000,
    "ok" : 0
}

以下為所有測試指令的集合

db.mate.ensureIndex({age:1});
db.mate.getIndexes();

db.mate.dropIndexes();
db.mate.ensureIndex({age:1, room:1});
db.mate.find().sort( {age:1, room:1});
db.mate.find().sort( {age:-1, room:1});
db.mate.getIndexes();

db.mate.dropIndexes();
db.mate.ensureIndex({userid:1}, {unique:true});
db.mate.ensureIndex({age:1}, {unique:true});

查詢最佳化

首先確認 db 有為 age, room 建立 index

> db.mate.dropIndexes();
{
    "nIndexesWas" : 2,
    "msg" : "non-_id indexes dropped for collection",
    "ok" : 1
}
> db.mate.ensureIndex({age:1, room:1});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> db.mate.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.mate"
    },
    {
        "v" : 1,
        "key" : {
            "age" : 1,
            "room" : 1
        },
        "name" : "age_1_room_1",
        "ns" : "test.mate"
    }
]

執行 find 條件查詢,可以用 explain() 確認是否有使用到 index。Explain Results 頁面可查看裡面每個欄位的意義。

結果中主要應該是看 winningPlan,這是 query optimizer 最後所選擇的 query plan。

Stage 表示該階段的 operation,有下列幾種

  1. COLLSCAN: collection scan,掃描整個 collection,如果有產生這個 stage,就表示這個查詢的速度會很慢
  2. IXSCAN: scanning index keys,掃描 index 的 keys
  3. FETCH: retrieveing documents,取得文件
  4. SHARD_MERGE: 由 shards 整合結果
  5. PROJECTION: Projections 表示針對collection的某些欄位進行篩檢
  6. KEEP_MUTATIONS: 還沒查到說明的頁面
    > db.mate.find( {age:{ $gt: 22}, username:{ $regex:/^M.*/ }} );
    { "_id" : ObjectId("5641980c997bc79c93b12e77"), "userid" : "mary", "username" : "Mary Wang", "city" : "Tainan", "age" : 23, "room" : "601" }
    > db.mate.find( {age:{ $gt: 22}, username:{ $regex:/^M.*/ }} ).explain();
    {
     "queryPlanner" : {
         "plannerVersion" : 1,
         "namespace" : "test.mate",
         "indexFilterSet" : false,
         "parsedQuery" : {
             "$and" : [
                 {
                     "age" : {
                         "$gt" : 22
                     }
                 },
                 {
                     "username" : /^M.*/
                 }
             ]
         },
         "winningPlan" : {
             "stage" : "KEEP_MUTATIONS",
             "inputStage" : {
                 "stage" : "FETCH",
                 "filter" : {
                     "username" : /^M.*/
                 },
                 "inputStage" : {
                     "stage" : "IXSCAN",
                     "keyPattern" : {
                         "age" : 1,
                         "room" : 1
                     },
                     "indexName" : "age_1_room_1",
                     "isMultiKey" : false,
                     "direction" : "forward",
                     "indexBounds" : {
                         "age" : [
                             "(22.0, inf.0]"
                         ],
                         "room" : [
                             "[MinKey, MaxKey]"
                         ]
                     }
                 }
             }
         },
         "rejectedPlans" : [ ]
     },
     "serverInfo" : {
         "host" : "server",
         "port" : 27017,
         "version" : "3.0.7",
         "gitVersion" : "6ce7cbe8c6b899552dadd907604559806aa2e9bd"
     },
     "ok" : 1
    }
    

搜尋的另一個例子

> db.mate.find( {age:{ $gt: 22}}, {username:1} );
{ "_id" : ObjectId("5641980c997bc79c93b12e77"), "username" : "Mary Wang" }
> db.mate.find( {age:{ $gt: 22}}, {username:1} ).explain();
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.mate",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "age" : {
                "$gt" : 22
            }
        },
        "winningPlan" : {
            "stage" : "PROJECTION",
            "transformBy" : {
                "username" : 1
            },
            "inputStage" : {
                "stage" : "FETCH",
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "age" : 1,
                        "room" : 1
                    },
                    "indexName" : "age_1_room_1",
                    "isMultiKey" : false,
                    "direction" : "forward",
                    "indexBounds" : {
                        "age" : [
                            "(22.0, inf.0]"
                        ],
                        "room" : [
                            "[MinKey, MaxKey]"
                        ]
                    }
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "kokola",
        "port" : 27017,
        "version" : "3.0.7",
        "gitVersion" : "6ce7cbe8c6b899552dadd907604559806aa2e9bd"
    },
    "ok" : 1
}

由於沒有 city 欄位的 index,因此產生了 COLLSCAN,當資料量大,這個查詢的速度將會變得很慢。

> db.mate.find( {city:{ $regex:/^T.*/ } } );
{ "_id" : ObjectId("5641980c997bc79c93b12e75"), "userid" : "john", "username" : "John Lin", "city" : "Taipei", "age" : 20, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e76"), "userid" : "muder", "username" : "Muder Yen", "city" : "Taichung", "age" : 19, "room" : "301" }
{ "_id" : ObjectId("5641980c997bc79c93b12e77"), "userid" : "mary", "username" : "Mary Wang", "city" : "Tainan", "age" : 23, "room" : "601" }
{ "_id" : ObjectId("5641980c997bc79c93b12e78"), "userid" : "celina", "username" : "Celina Lin", "city" : "Taichung", "age" : 20, "room" : "601" }
{ "_id" : ObjectId("5641980c997bc79c93b12e7a"), "userid" : "danny", "username" : "Danny Huang", "city" : "Taipei" }
{ "_id" : ObjectId("5641980c997bc79c93b12e7b"), "userid" : "johnny", "username" : "Johnny Lo", "city" : "Taipei", "age" : null }
> db.mate.find( {city:{ $regex:/^T.*/ } } ).explain();
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.mate",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "city" : /^T.*/
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "city" : /^T.*/
            },
            "direction" : "forward"
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "kokola",
        "port" : 27017,
        "version" : "3.0.7",
        "gitVersion" : "6ce7cbe8c6b899552dadd907604559806aa2e9bd"
    },
    "ok" : 1
}

以下為所有測試指令的集合

db.mate.dropIndexes();
db.mate.ensureIndex({age:1});
db.mate.ensureIndex({room:1});
db.mate.getIndexes();


db.mate.find( {age:{ $gt: 22}, username:{ $regex:/^M.*/ }} );
db.mate.find( {age:{ $gt: 22}, username:{ $regex:/^M.*/ }} ).explain();

db.mate.find( {age:{ $gt: 22}}, {username:1} );
db.mate.find( {age:{ $gt: 22}}, {username:1} ).explain();

db.mate.find( {city:{ $regex:/^T.*/ } } );
db.mate.find( {city:{ $regex:/^T.*/ } } ).explain();

Profiler

MongoDB 中,可以啟動 profiler,用來記錄一些速度較慢的查詢指令,這可以用來作為最佳化資料庫的資訊來源。

有兩種方式可以啟動 profile 的功能,第一種是直接在 mongod 的參數中,加上 -profile ,第二種是透過 db.setProfilingLevel()來啟動 profiler。

profiler level 有三種

  • 0: 不啟動
  • 1: 記錄慢指令(預設為 > 100ms)
  • 2: 記錄所有指令

可用以下指令設定 ProfilingLevel

db.setProfilingLevel(1);

也可以同時指定慢指令的時間,例如設定為 10ms

db.setProfilingLevel(1,10);

查看執行時間超過 5ms 的 profiler 記錄

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

查看最新的 profiler 記錄

db.system.profile.find().sort({$natural:-1}).limit(5);

> db.system.profile.find().sort({$natural:-1}).limit(5);
{ "op" : "query", "ns" : "test.mate", "query" : { "age" : { "$gt" : 22 }, "username" : { "$regex" : /^M.*/ } }, "ntoreturn" : 0, "ntoskip" : 0, "nscanned" : 1, "nscannedObjects" : 1, "keyUpdates" : 0, "writeConflicts" : 0, "numYield" : 0, "locks" : { "Global" : { "acquireCount" : { "r" : NumberLong(2) } }, "MMAPV1Journal" : { "acquireCount" : { "r" : NumberLong(1) } }, "Database" : { "acquireCount" : { "r" : NumberLong(1) } }, "Collection" : { "acquireCount" : { "R" : NumberLong(1) } } }, "nreturned" : 1, "responseLength" : 127, "millis" : 0, "execStats" : { "stage" : "KEEP_MUTATIONS", "nReturned" : 1, "executionTimeMillisEstimate" : 0, "works" : 2, "advanced" : 1, "needTime" : 0, "needFetch" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "inputStage" : { "stage" : "FETCH", "filter" : { "username" : /^M.*/ }, "nReturned" : 1, "executionTimeMillisEstimate" : 0, "works" : 2, "advanced" : 1, "needTime" : 0, "needFetch" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "docsExamined" : 1, "alreadyHasObj" : 0, "inputStage" : { "stage" : "IXSCAN", "nReturned" : 1, "executionTimeMillisEstimate" : 0, "works" : 1, "advanced" : 1, "needTime" : 0, "needFetch" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "invalidates" : 0, "keyPattern" : { "age" : 1 }, "indexName" : "age_1", "isMultiKey" : false, "direction" : "forward", "indexBounds" : { "age" : [ "(22.0, inf.0]" ] }, "keysExamined" : 1, "dupsTested" : 0, "dupsDropped" : 0, "seenInvalidated" : 0, "matchTested" : 0 } } }, "ts" : ISODate("2015-11-11T03:22:04.503Z"), "client" : "127.0.0.1", "allUsers" : [ ], "user" : "" }

最佳化的策略方案

  1. 建立索引
    針對查詢條件的欄位建立索引
  2. 限制回傳結果的筆數
    使用 limit() 限制筆數,可減少 db 的資源消耗並減少網路傳輸量
  3. 只查詢使用到的欄位,不查詢所有欄位
    只查詢使用到的欄位
  4. 使用 Capped Collection
    Capped Collection 比普通的 Collection 的讀寫效率高,它有以下的特性
    • 固定大小:必須手動建立並設定固定的大小,db.createcollection("testc", {capped:true, size:1000000});
    • 可以 insert 與 update 但不能 delete
    • 只能用 drop 刪除整個 collection
    • 預設以 insert 的順序排序
    • FIFO,如果超過了限制的大小,依照 FIFO 原則,自動刪除最舊的資料
  5. 使用 Server Side Code Execution
    類似關聯式資料庫的 Stored Procedure
  6. hint
    一般情況下使用 query optimizer 就好了,有時候可以用 hint() 強制要求查詢要使用某個 index。例如在多個條件的查詢中,如果其中一個欄位有索引,可以用 hint

     > db.mate.find( {age:{ $gt: 22}}, {username:1} ).hint({age:1});
     { "_id" : ObjectId("5641980c997bc79c93b12e77"), "username" : "Mary Wang" }
     > db.mate.find( {age:{ $gt: 22}}, {username:1} ).hint({age:1}).explain)(;
     2015-11-11T11:35:22.023+0800 E QUERY    SyntaxError: Unexpected token )
     > db.mate.find( {age:{ $gt: 22}}, {username:1} ).hint({age:1}).explain();
     {
         "queryPlanner" : {
             "plannerVersion" : 1,
             "namespace" : "test.mate",
             "indexFilterSet" : false,
             "parsedQuery" : {
                 "age" : {
                     "$gt" : 22
                 }
             },
             "winningPlan" : {
                 "stage" : "PROJECTION",
                 "transformBy" : {
                     "username" : 1
                 },
                 "inputStage" : {
                     "stage" : "FETCH",
                     "inputStage" : {
                         "stage" : "IXSCAN",
                         "keyPattern" : {
                             "age" : 1
                         },
                         "indexName" : "age_1",
                         "isMultiKey" : false,
                         "direction" : "forward",
                         "indexBounds" : {
                             "age" : [
                                 "(22.0, inf.0]"
                             ]
                         }
                     }
                 }
             },
             "rejectedPlans" : [ ]
         },
         "serverInfo" : {
             "host" : "server",
             "port" : 27017,
             "version" : "3.0.7",
             "gitVersion" : "6ce7cbe8c6b899552dadd907604559806aa2e9bd"
         },
         "ok" : 1
     }
    
  7. 使用 profiling
    利用 profiling 記錄一些比較慢的查詢,用來作為後續最佳化的參考資料

資料庫監控

  • mongosniff
    binary 安裝包裡面並沒有包含這個工具,必須要自己從 source code 編譯,這個工具可以監聽 27017 port,記錄所有封包。

  • mongostat
    可查詢某個 mongod 的統計資訊

    [root@kokola bin]# ./mongostat
    insert query update delete getmore command flushes mapped vsize   res faults qr|qw ar|aw netIn netOut conn     time
      *0    *0     *0     *0       0     1|0       0 160.0M  1.7G 73.0M      0   0|0   0|0   79b    10k    2 11:42:14
      *0    *0     *0     *0       0     1|0       0 160.0M  1.7G 73.0M      0   0|0   0|0   79b    10k    2 11:42:15
      *0    *0     *0     *0       0     1|0       0 160.0M  1.7G 73.0M      0   0|0   0|0   79b    10k    2 11:42:16
      *0    *0     *0     *0       0     1|0       0 160.0M  1.7G 73.0M      0   0|0   0|0   79b    10k    2 11:42:17
      *0    *0     *0     *0       0     2|0       0 160.0M  1.7G 73.0M      0   0|0   0|0  133b    10k    2 11:42:18
      *0    *0     *0     *0       0     1|0       0 160.0M  1.7G 73.0M      0   0|0   0|0   79b    10k    2 11:42:19
    
      insert
          每秒 insert 的operation數量
      query
      update
      delete
      getmore
          每秒進行 get more (ex: cursor batch) operations 的數量
      command
          每秒執行的指令數量
      flushes
          如果是 WiredTiger Storage Engine就是 WiredTiger checkpoints triggered 的數量,如果是 MMAPv1 Storage Engine,就是 fsync operations 的數量
      dirty
          只有 WiredTiger Storage Engine 會有,這是 WiredTiger cache with dirty bytes 的比例
      used
          WiredTiger Storage Engine 才有,這是 WiredTiger cache 的使用比例
      mapped
          MMAPv1 Storage Engine 才有,總資料量,單位是 MegaBytes
      vsize
          mongod proecess 使用的 virtual memory 數量,單位是 MegaBytes
      non-mapped
          (optional) MMAPv1 Storage Engine 才有,去掉所有 mapped memory 的 virtual memory 總量
      res
          process 使用的 resident memory 總量,單位是 MegaBytes
      faults
          MMAPv1 Storage Engine 才有,每秒產生的 page faults 數量
      idx miss
          MMAPv1 Storage Engine才有,載入一個 btree node 所產生的 page fault,所需要使用的 index 比例
      qr
          所有 clients 等待讀取資料的 queue 的長度
      qw
          所有 clients 等待寫入資料的 queue 的長度
      ar
          執行 read operations 的 active clients 數量
      aw
          執行 write operations 的 active clients 數量
      netIn
          mongod 由網路接收到的資料量,單位為 bytes,包含 mongostat 本身的資料量
      netOut
          mongod 由網路發送的資料量,單位為 bytes
      conn
          總連線數
      set
          replica set 的名稱
      repl
          replication status of the members
          (1) M: master
          (2) SEC: secondary
          (3) REC: recovering
          (4) UNK: unknown
          (5) SLV: slave
          (6) RTR: mongos process(router)
          (7) ARB: arbiter
    

db.serverStatus

透過 db.serverStatus() 指令,我們可以即時檢視資料庫的狀態。

> db.serverStatus();
{
    "host" : "server",
    "version" : "3.0.7",    // MongoDB 版本
    "process" : "mongod",
    "pid" : NumberLong(12533), // processid
    "uptime" : 160841,    // 啟動的時間(seconds)
    "uptimeMillis" : NumberLong(160841652),
    "uptimeEstimate" : 159741,
    "localTime" : ISODate("2015-11-11T06:27:31.655Z"),
    "asserts" : {    // server 產生 error or assertions 的數量
        "regular" : 0,
        "warning" : 0,
        "msg" : 0,
        "user" : 9,
        "rollovers" : 0
    },
    "backgroundFlushing" : {    // 將資料寫入 disk 的 report
        "flushes" : 2680,
        "total_ms" : 4357,
        "average_ms" : 1.6257462686567163,
        "last_ms" : 1,
        "last_finished" : ISODate("2015-11-11T06:26:50.271Z")
    },
    "connections" : {    // 目前clients的連線狀況
        "current" : 1,    // active client 連線數量
        "available" : 52427,    // 空閒的連線數量
        "totalCreated" : NumberLong(4)
    },
    "cursors" : {    // 目前的 cursor 使用狀況
        "note" : "deprecated, use server status metrics",
        "clientCursors_size" : 0,
        "totalOpen" : 0,
        "pinned" : 0,
        "totalNoTimeout" : 0,
        "timedOut" : 3
    },
    "dur" : {    // journaling 的 report
        "commits" : 22,
        "journaledMB" : 0,
        "writeToDataFilesMB" : 0,
        "compression" : 0,
        "commitsInWriteLock" : 0,
        "earlyCommits" : 0,
        "timeMs" : {
            "dt" : 0,
            "prepLogBuffer" : 0,
            "writeToJournal" : 0,
            "writeToDataFiles" : 0,
            "remapPrivateView" : 0,
            "commits" : 0,
            "commitsInWriteLock" : 0
        }
    },
    "extra_info" : {
        "note" : "fields vary by platform",
        "heap_usage_bytes" : 63700688,
        "page_faults" : 65
    },
    "globalLock" : {    // global system lock 的 report
        "totalTime" : NumberLong("160841653000"),
        "currentQueue" : {
            "total" : 0,    // 全部 queue 的數量
            "readers" : 0,
            "writers" : 0
        },
        "activeClients" : {
            "total" : 9,    // client連線數量
            "readers" : 0,
            "writers" : 0
        }
    },
    "locks" : {        // 每個 lock type 與 mode 的統計報告
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(539117),
                "w" : NumberLong(559),
                "W" : NumberLong(50)
            }
        },
        "MMAPV1Journal" : {
            "acquireCount" : {
                "r" : NumberLong(269221),
                "w" : NumberLong(1214),
                "R" : NumberLong(1573490),
                "W" : NumberLong(6)
            },
            "acquireWaitCount" : {
                "w" : NumberLong(1),
                "R" : NumberLong(2)
            },
            "timeAcquiringMicros" : {
                "w" : NumberLong(18),
                "R" : NumberLong(173851)
            }
        },
        "Database" : {
            "acquireCount" : {
                "r" : NumberLong(269199),
                "w" : NumberLong(391),
                "R" : NumberLong(55),
                "W" : NumberLong(201)
            }
        },
        "Collection" : {
            "acquireCount" : {
                "R" : NumberLong(281400),
                "W" : NumberLong(442)
            }
        },
        "Metadata" : {
            "acquireCount" : {
                "W" : NumberLong(180)
            }
        }
    },
    "network" : {    // 網路的使用報告
        "bytesIn" : NumberLong(111181),
        "bytesOut" : NumberLong(354420),
        "numRequests" : NumberLong(1227)
    },
    "opcounters" : {    // 這個 instance 處理了幾個 operations
        "insert" : 200,
        "query" : 158,
        "update" : 3,
        "delete" : 2,
        "getmore" : 3,
        "command" : 973
    },
    "opcountersRepl" : {    // 處理了幾個 replicated operations
        "insert" : 0,
        "query" : 0,
        "update" : 0,
        "delete" : 0,
        "getmore" : 0,
        "command" : 0
    },
    "storageEngine" : {        // 目前使用那一種 storage engine
        "name" : "mmapv1"
    },
    "writeBacksQueued" : false,
    "mem" : {    // 目前記憶體的使用報告
        "bits" : 64,    // 64 bits
        "resident" : 73,    // 佔用的物理記憶體總量
        "virtual" : 1750,    // 虛擬記憶體總量
        "supported" : true,    // 是否支援擴充記憶體
        "mapped" : 160,
        "mappedWithJournal" : 320
    },
    "metrics" : {    // 監控 mongod 的 state 與 workload 的一些 operational metrics
        "commands" : {
            "<UNKNOWN>" : NumberLong(1),
            "collStats" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(2)
            },
            "count" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(2)
            },
            "createIndexes" : {
                "failed" : NumberLong(2),
                "total" : NumberLong(13)
            },
            "delete" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(2)
            },
            "drop" : {
                "failed" : NumberLong(63),
                "total" : NumberLong(85)
            },
            "dropIndexes" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(7)
            },
            "explain" : {
                "failed" : NumberLong(1),
                "total" : NumberLong(18)
            },
            "getLog" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(3)
            },
            "getnonce" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(1)
            },
            "insert" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(200)
            },
            "isMaster" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(740)
            },
            "listCollections" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(38)
            },
            "listIndexes" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(11)
            },
            "mapReduce" : {
                "failed" : NumberLong(1),
                "total" : NumberLong(16)
            },
            "ping" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(3)
            },
            "profile" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(2)
            },
            "renameCollection" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(15)
            },
            "replSetGetStatus" : {
                "failed" : NumberLong(3),
                "total" : NumberLong(3)
            },
            "serverStatus" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(11)
            },
            "update" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(3)
            },
            "whatsmyuri" : {
                "failed" : NumberLong(0),
                "total" : NumberLong(3)
            }
        },
        "cursor" : {
            "timedOut" : NumberLong(3),
            "open" : {
                "noTimeout" : NumberLong(0),
                "pinned" : NumberLong(0),
                "total" : NumberLong(0)
            }
        },
        "document" : {
            "deleted" : NumberLong(1),
            "inserted" : NumberLong(199),
            "returned" : NumberLong(1279),
            "updated" : NumberLong(3)
        },
        "getLastError" : {
            "wtime" : {
                "num" : 0,
                "totalMillis" : 0
            },
            "wtimeouts" : NumberLong(0)
        },
        "operation" : {
            "fastmod" : NumberLong(0),
            "idhack" : NumberLong(0),
            "scanAndOrder" : NumberLong(7),
            "writeConflicts" : NumberLong(0)
        },
        "queryExecutor" : {
            "scanned" : NumberLong(34),
            "scannedObjects" : NumberLong(1824)
        },
        "record" : {
            "moves" : NumberLong(0)
        },
        "repl" : {
            "apply" : {
                "batches" : {
                    "num" : 0,
                    "totalMillis" : 0
                },
                "ops" : NumberLong(0)
            },
            "buffer" : {
                "count" : NumberLong(0),
                "maxSizeBytes" : 268435456,
                "sizeBytes" : NumberLong(0)
            },
            "network" : {
                "bytes" : NumberLong(0),
                "getmores" : {
                    "num" : 0,
                    "totalMillis" : 0
                },
                "ops" : NumberLong(0),
                "readersCreated" : NumberLong(0)
            },
            "preload" : {
                "docs" : {
                    "num" : 0,
                    "totalMillis" : 0
                },
                "indexes" : {
                    "num" : 0,
                    "totalMillis" : 0
                }
            }
        },
        "storage" : {
            "freelist" : {
                "search" : {
                    "bucketExhausted" : NumberLong(0),
                    "requests" : NumberLong(611),
                    "scanned" : NumberLong(0)
                }
            }
        },
        "ttl" : {
            "deletedDocuments" : NumberLong(0),
            "passes" : NumberLong(2680)
        }
    },
    "ok" : 1
}

db.stats

db.stats 指令是用來查看 dbStats 資料庫的狀態

> db.stats();
{
    "db" : "test",
    "collections" : 5,    // connection 數量
    "objects" : 28,        // 物件數量
    "avgObjSize" : 307.42857142857144,    // 平均物件大小
    "dataSize" : 8608,    // 資料大小
    "storageSize" : 1110016,    // storage大小
    "numExtents" : 6,    // 事件數量
    "indexes" : 4,        // 索引數量
    "indexSize" : 32704,    // 索引大小
    "fileSize" : 67108864,    // 檔案大小
    "nsSizeMB" : 16,
    "extentFreeList" : {
        "num" : 3,
        "totalSize" : 147456
    },
    "dataFileVersion" : {
        "major" : 4,
        "minor" : 22
    },
    "ok" : 1
}