如何監控 MongoDB 的效能

作者選擇了開放網際網路/言論自由基金作為寫作捐贈計劃的捐贈對象。

介紹

監控是數據庫管理的關鍵部分,因為它使您能夠了解數據庫的性能和整體健康狀況。通過監控您的數據庫性能,您可以更好地了解其當前容量,觀察其工作負載隨時間的變化,並提前計劃擴展數據庫,一旦它開始接近其極限。它還可以幫助您注意到潛在的硬件問題或異常行為,如數據庫使用意外增加。最後,監控還可以幫助診斷使用數據庫的應用程序的問題,例如導致瓶頸的應用程序查詢。

MongoDB預安裝了各種工具和實用程序,您可以使用這些工具觀察數據庫的性能。在本教程中,您將學習如何使用內置命令和工具按需監控數據庫指標。您還將熟悉MongoDB的數據庫分析器,它可以幫助您檢測優化不佳的查詢。

先決條件

要遵循此教程,您需要:

注意:有关如何配置服务器、安装MongoDB和保护MongoDB安装的链接教程都是针对Ubuntu 20.04的。本教程集中讨论MongoDB本身,而不是底层操作系统。只要启用了身份验证,它通常适用于任何MongoDB安装,无论操作系统如何。

第1步 — 准备测试数据

为了解释如何监视MongoDB的性能,此步骤概述了如何打开MongoDB shell以连接到您本地安装的MongoDB实例,并在其中创建一个示例集合。

為了創建本指南中使用的樣本集合,請連接到 MongoDB shell 作為您的管理用戶。本教程遵循先決條件 MongoDB 安全教程 的約定,假定此管理用戶的名稱為 AdminSammy,其驗證數據庫為 admin。請確保在以下命令中更改這些細節以反映您自己的設置,如果有不同:

  1. mongo -u AdminSammy -p --authenticationDatabase admin

輸入安裝過程中設置的密碼以獲取對 shell 的訪問權限。提供密碼後,您將看到提示符 >

注意: 在新的連接上,MongoDB shell 將默認連接到 test 數據庫。您可以安全地使用此數據庫來進行 MongoDB 和 MongoDB shell 的實驗。

或者,您可以切換到另一個數據庫來運行本教程中給出的所有示例命令。要切換到另一個數據庫,請運行 use 命令,然後跟上您的數據庫的名稱:

  1. use database_name

在處理小數據集時,數據庫監控並不是非常實用或有用,因為數據庫系統只需要掃描幾條記錄就可以對任何給定的查詢進行操作。為了說明 MongoDB 的性能監控功能,您需要一個具有足夠數據的數據庫,以便 MongoDB 執行查詢需要相當長的時間。

為此,本指南中的示例參考了一個名為accounts的示例集合,其中包含大量文件。每個文件代表一個帶有隨機生成的帳戶餘額的個人銀行帳戶。集合中的每個文件都會有以下結構:

An example bank account document
{
    "number": "1000-987321",
    "currency": "USD",
    "balance": 431233431
}

此示例文件包含以下信息:

  • number:此字段表示給定帳戶的帳戶號碼。在此集合中,每個帳戶號碼都將以1000-為前綴,後跟遞增的數字標識符。
  • currency:此字段指示每個帳戶餘額存儲在哪種類型的貨幣中。每個帳戶的currency值將是USDEUR
  • balance:這顯示了每個給定銀行帳戶的餘額。在此樣本數據庫中,每個文件的balance字段將具有隨機生成的值。

您可以執行以下JavaScript代碼,而不是手動插入大量文件,以同時創建一個名為accounts的集合並將一百萬個這樣的文件插入其中:

  1. for (let i = 1; i <= 1000000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "1000-" + i,
  4. "currency": i > 500000 ? "USD" : "EUR",
  5. "balance": Math.random() * 100000
  6. })
  7. }

此代碼執行一個 for 循環,連續運行一百萬次。每次循環迭代時,它會在帳戶集合上執行一個 insertOne() 方法來插入一個新文檔。在每次迭代中,該方法會給 number 字段賦值,該值由該迭代的 i 值組成。這意味著第一次循環迭代時,number 字段的值將設置為 1000-1;最後一次迭代時,它將被設置為 1000-1000000

對於帳戶號大於500000的帳戶,貨幣始終表示為 USD,對於帳戶號低於該值的帳戶,則表示為 EUR。餘額字段使用 Math.random() 函數生成介於0和1之間的隨機數,然後將該隨機數乘以100000以提供較大的值。

注意: 執行此循環可能需要很長時間,甚至超過10分鐘。可以安全地將操作保持運行,直到完成為止。

輸出將通知您操作的成功,並返回最後插入的文檔的 ObjectId

Output
{ "acknowledged" : true, "insertedId" : ObjectId("61a38a4beedf737ac8e54e82") }

您可以通過運行不帶參數的 count() 方法來驗證文檔是否被正確插入,該方法將檢索集合中文檔的計數:

  1. db.accounts.count()
Output
1000000

在此步驟中,您已成功創建了示例文檔列表,該列表將作為本指南中用於解釋 MongoDB 提供的性能監控工具的測試數據。在下一步中,您將學習如何檢查基本的服務器使用統計信息。

第二步 — 檢查伺服器使用統計

MongoDB自動追蹤一些有用的性能統計數據,定期檢查這些數據是監控您的數據庫的基本方法。請注意,這些統計數據不會提供關於您的數據庫正在發生的實時洞察,但它們可以用於確定數據庫的性能如何以及是否存在任何即將出現的問題。

警告:本指南中概述的MongoDB監控命令會返回有關您的數據庫及其性能的潛在敏感信息。因此,其中一些命令需要高級權限。

具體來說,在本步驟中概述的serverStatus()方法以及在下一步中突出顯示的mongostatmongotop命令都需要使用者被授予clusterMonitor角色才能運行它們。同樣,第4步中概述的setProfilingLevel()方法需要dbAdmin角色。

假設您已經按照如何在Ubuntu 20.04上保護MongoDB的先決教程進行了操作並作為該指南中創建的管理用戶連接到您的MongoDB實例,您將需要授予它這些附加角色以便跟隨本指南中的示例。

首先,切換到您的使用者驗證資料庫。在下面的範例中,這是admin,但如果不同的話,請連接到您自己使用者的驗證資料庫:

  1. use admin
Output
switched to db admin

然後執行grantRolesToUser()方法,並授予您的使用者clusterMonitor角色以及dbAdmin角色,覆蓋您建立accounts收集的資料庫。以下範例假設accounts收集位於test資料庫中:

  1. db.grantRolesToUser(
  2. "AdminSammy",
  3. [
  4. "clusterMonitor",
  5. { role : "dbAdmin", db : "test" }
  6. ]
  7. )

請注意,通常認為將使用者配置為專用用途更為安全。這樣,沒有使用者會擁有不必要的廣泛權限。如果您在生產環境中工作,您可能希望有一個專用的使用者,其唯一目的是監控資料庫。

以下範例創建了一個名為MonitorSammy的 MongoDB 使用者,並授予了他們您在本教程中使用的範例所需的角色。請注意,它還包括readWriteAnyDatabase角色,這將允許此使用者讀取和寫入叢集中的任何資料庫:

  1. db.createUser(
  2. {
  3. user: "MonitorSammy",
  4. pwd: passwordPrompt(),
  5. roles: [ { role : "dbAdmin", db : "test" }, "clusterMonitor", "readWriteAnyDatabase" ]
  6. }
  7. )

在授予您的使用者適當的角色之後,返回到存儲您的accounts收集的資料庫:

  1. use test
Output
switched to db test

首先,通過執行stats()方法檢查整個資料庫的統計資訊:

  1. db.stats(1024*1024)

此方法的參數(1024*1024)是比例因子,並告訴 MongoDB 將儲存資訊以兆位為單位返回。如果省略此參數,則所有值都將以位元組形式呈現。

stats() 方法返回一個簡短而簡潔的輸出,其中包含與當前數據庫相關的一些重要統計信息:

Output
{ "db" : "test", "collections" : 3, "views" : 0, "objects" : 1000017, "avgObjSize" : 80.8896048767171, "dataSize" : 77.14365005493164, "storageSize" : 24.109375, "indexes" : 4, "indexSize" : 9.9765625, "totalSize" : 34.0859375, "scaleFactor" : 1048576, "fsUsedSize" : 4238.12109375, "fsTotalSize" : 24635.703125, "ok" : 1 }

此輸出提供了此 MongoDB 實例正在存儲的數據的概述。在此輸出中返回的以下鍵可能特別有用:

  • objects 鍵顯示了數據庫中文檔的總數。您可以使用此來評估數據庫的大小,並且隨著時間的推移,了解其增長情況。
  • avgObjectSize 顯示了這些文檔的平均大小,提供了有關數據庫是在處理大型和複雜文檔還是小型文檔的見解。無論您是否指定了比例因子,此值始終以字節形式顯示。
  • collectionsindexes 鍵顯示了數據庫中目前定義的集合和索引的數量。
  • totalSize 鍵指示了數據庫在磁盤上占用了多少存儲空間。

stats() 方法返回的此信息可幫助您了解當前存儲在您的數據庫中的數據量,但它並未提供有關其性能或現有問題的見解。為此,更加冗長的 serverStatus() 方法非常有用:

  1. db.serverStatus()

此方法的輸出很長,並且提供了有關服務器使用情況的大量信息:

Output
{ "host" : "ubuntu-mongo-rs", "version" : "4.4.6", "process" : "mongod", "pid" : NumberLong(658997), "uptime" : 976, . . . "ok" : 1 }

儘管所有這些信息都可能有用,但本指南將特別關注三個部分。首先,查找此輸出的 connections 部分:

Output
. . . "connections" : { "current" : 4, "available" : 51196, "totalCreated" : 4, "active" : 2, "exhaustIsMaster" : 1, "exhaustHello" : 0, "awaitingTopologyChanges" : 1 }, . . .

每個數據庫伺服器一次只能支援有限數量的連接。current鍵顯示目前連接到數據庫的客戶端數量,而available則是數據庫可用的剩餘未使用連接的數量。totalCreated值保持從伺服器啟動以來已使用的連接數量。

大多數應用程序都設計為重複使用現有連接,不經常開啟多個連接。因此,如果沒有預料到的情況下出現大量連接,可能表明客戶端訪問服務器的配置不正確。

如果預期會有大量連接,可能考慮向分片集群添加一個或多個分片,以將流量分發到多個MongoDB實例中。

接下來,找到輸出的globalLock部分。該部分涉及整個數據庫伺服器的全局鎖:

Output
. . . "globalLock" : { "totalTime" : NumberLong(975312000), "currentQueue" : { "total" : 0, "readers" : 0, "writers" : 0 }, "activeClients" : { "total" : 0, "readers" : 0, "writers" : 0 } },

MongoDB使用鎖定來確保在執行多個操作時數據的一致性,保證沒有兩個查詢會同時修改同一數據。在使用頻繁的伺服器上,有可能出現鎖定造成瓶頸的情況,一個或多個查詢可能會等待鎖定釋放才能執行。

currentQueue.total值顯示正在等待鎖定釋放以便執行的查詢數量。如果這個值很高,則表示數據庫的性能受到影響,查詢將需要更長的時間來完成。

這通常源於許多長時間運行的查詢持有鎖定,可能表明索引使用不當或查詢設計不佳,還有其他可能性。

最後,找到opcounters部分:

Output
"opcounters" : { "insert" : NumberLong(10000007), "query" : NumberLong(6), "update" : NumberLong(6), "delete" : NumberLong(0), "getmore" : NumberLong(0), "command" : NumberLong(1298) },

此部分的serverStatus()輸出可以幫助您了解數據庫服務器主要用於讀取還是寫入,或者使用是否平衡。在這個例子中,在插入測試文檔之後,insert操作的計數要比query操作高得多。在實際場景中,這些值可能會不同。

寫入密集型數據庫可以通過分片進行橫向擴展。同樣,讀取密集型的MongoDB數據庫通常會從複製中受益。

這些統計數據可以總體上了解服務器的使用情況,以及在訪問時是否存在長時間的鎖定隊列等性能問題。但是,它們不提供關於服務器實際使用情況的即時信息。為此,mongostatmongotop命令是有用的工具。

步驟 3 — 使用 mongostatmongotop 獲取即時數據庫統計資訊

雖然用於訪問 MongoDB 伺服器統計資訊的命令可以提供對伺服器如何運作的回顧性洞察,但它們無法提供即時資訊,即目前哪些集合正在被最活躍地使用,或正在執行什麼樣的查詢。

MongoDB 提供了兩個有用的系統工具進行即時監控,分析數據庫活動並持續刷新它們所提供的資訊:mongostatmongotopmongostat 提供 MongoDB 實例當前狀態的簡要概述,而 mongotop 則追蹤實例花費在讀取和寫入操作上的時間。這兩個工具都是從命令行運行,而不是從 MongoDB shell 運行。

要使用 mongostat,保持您當前的 MongoDB shell 連接,並打開另一個終端窗口來訪問您的伺服器 shell。在第二個伺服器 shell 中,執行 mongostat 命令:

  1. mongostat -u AdminSammy --authenticationDatabase admin

如先前所述,mongostat 需要高级权限。如果您已在 MongoDB 实例上启用了身份验证并设置了具有适当角色的用户,则必须通过提供其用户名和身份验证数据库(如本示例所示)进行身份验证,然后在提示时输入其密码。

在默认配置中,mongostat 每秒打印当前执行的查询计数:

Output
insert query update delete getmore command dirty used flushes vsize res qrw arw net_in net_out conn time *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 223b 84.4k 7 Nov 28 15:40:40.621 *0 *0 *0 *0 0 2|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 224b 84.8k 7 Nov 28 15:40:41.619 *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 223b 84.5k 7 Nov 28 15:40:42.621 *0 *0 *0 *0 0 3|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 365b 85.0k 7 Nov 28 15:40:43.619

如果 mongostat 输出显示某个查询类型的值为 0,则表示数据库未运行该类型的任何操作。此示例输出显示每个查询类型的 0,这意味着当前没有任何查询在活动中。

您仍应保持第一个终端窗口处于打开状态并连接到您的 MongoDB shell。向 accounts 集合插入更多测试文档,并检查 mongostat 是否会注意到活动:

  1. for (let i = 1; i <= 10000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "2000-" + i,
  4. "currency": "USD",
  5. "balance": Math.random() * 100000
  6. })
  7. }

这是一个类似于您在步骤 1 中运行的 for 循环。不过,这次循环仅插入 10000 个条目。帐户号码以 2000 为前缀,货币始终为 USD。

在插入新文档时,检查 mongostat 输出:

Output
. . . *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 112b 42.5k 4 Nov 28 15:50:33.294 *0 *0 *0 *0 0 0|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 111b 42.2k 4 Nov 28 15:50:34.295 755 *0 *0 *0 0 1|0 0.1% 38.8% 0 1.54G 210M 0|0 1|0 154k 79.4k 4 Nov 28 15:50:35.294 2853 *0 *0 *0 0 0|0 0.4% 39.1% 0 1.54G 211M 0|0 1|0 585k 182k 4 Nov 28 15:50:36.295 2791 *0 *0 *0 0 1|0 0.7% 39.4% 0 1.54G 212M 0|0 1|0 572k 179k 4 Nov 28 15:50:37.293 2849 *0 *0 *0 0 0|0 1.0% 39.7% 0 1.54G 213M 0|0 1|0 584k 182k 4 Nov 28 15:50:38.296 745 *0 *0 *0 0 2|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 153k 79.2k 4 Nov 28 15:50:39.294 *0 *0 *0 *0 0 0|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 111b 42.2k 4 Nov 28 15:50:40.295 *0 *0 *0 *0 0 2|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 167b 42.7k 4 Nov 28 15:50:41.293 . . .

當查詢運行時,mongostat 返回的新行開始顯示除0之外的值。在顯示將新數據插入到數據庫的查詢數量的insert列中,數值在幾秒內較高。由於mongostat以一秒間隔顯示數據,因此您不僅可以找到插入相對於其他類型的數據庫操作的比例,還可以了解數據庫插入新數據的速度。在這個例子中,伺服器幾乎每秒達到了3000次插入。

您可以使用mongostat來監視數據庫伺服器的當前工作負載,按查詢類型分組。MongoDB隨附的第二個工具mongotop顯示按集合分組的數據庫伺服器活動。

通過按CTRL + C在第二個終端窗口中停止mongostat運行。然後在同一終端中運行mongotop。同樣,如果啟用了身份驗證,您需要以適當權限的用戶進行身份驗證:

  1. mongotop -u AdminSammy --authenticationDatabase admin

mongotop輸出數據庫中所有集合的列表,並伴隨在時間窗口內的讀取、寫入和總體花費的時間。與mongostat類似,輸出每秒刷新一次:

Output
2021-11-28T15:54:42.290+0000 connected to: mongodb://localhost/ ns total read write 2021-11-28T15:54:43Z admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms test.accounts 0ms 0ms 0ms . . .

嘗試向數據庫插入更多文檔,看看活動是否在mongotop中註冊。在MongoDB shell中,執行以下for循環;執行後,觀察運行mongotop的終端窗口:

  1. for (let i = 1; i <= 10000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "3000-" + i,
  4. "currency": "USD",
  5. "balance": Math.random() * 100000
  6. })
  7. }

這次,活動將在mongotop統計信息中可見:

Output
. . . ns total read write 2021-11-28T15:57:27Z test.accounts 127ms 0ms 127ms admin.$cmd.aggregate 0ms 0ms 0ms admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms ns total read write 2021-11-28T15:57:28Z test.accounts 130ms 0ms 130ms admin.$cmd.aggregate 0ms 0ms 0ms admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms . . .

這裡,mongotop 顯示所有的資料庫活動都發生在 test 資料庫的 accounts 集合中,而且在時間窗口內的所有操作都是寫入操作。所有這些都應該與您執行的 for 迴圈操作相一致。

mongostat 一樣,您可以通過按下 CTRL + C 來停止 mongotop 的運行。

在觀察到高峰負載時,您可以使用 mongotop 監控資料庫活動如何分佈到不同的集合,以幫助您更好地了解您的架構並計劃擴展。它還提供了有關集合使用是更讀還是更寫密集的見解。

步驟 4 — 使用 MongoDB 的資料庫分析器來識別慢查詢

資料庫性能瓶頸可能來自多個來源。儘管擴展資料庫(橫向或縱向)通常是解決性能瓶頸的方法,但其原因可能實際上不是資料庫的限制,而是架構或查詢設計的問題。

如果查詢運行時間過長,原因可能是索引的使用不效或查詢本身存在錯誤。長時間運行的查詢通常在應用開發過程中被忽略,主要是因為測試數據集太小或條件與生產環境不同。

你可以透過手動執行測試查詢並檢查哪些查詢表現不佳來潛在地找到罪魁禍首,但這將非常繁瑣。幸運的是,MongoDB 的資料庫分析器工具可以自動完成這項任務。

MongoDB 的資料庫分析器可以在符合某些條件時記錄查詢和其執行的統計資料。其中最重要的條件之一是查詢的執行時間:如果查詢執行所需的時間超過指定的時間,分析器將自動將該查詢標記為問題查詢。使用分析器,您可以識別出表現不佳的查詢,然後專注於解決這些特定問題。

在使用分析器之前,請執行以下查詢。該查詢將檢索您插入的其中一個帳戶,但這並不像乍看起來那麼簡單:

  1. db.accounts.find({"number": "1000-20"})

該命令將檢索您請求的確切帳戶:

Output
{ "_id" : ObjectId("61a38fd5eedf737ac8e54e96"), "number" : "1000-20", "currency" : "EUR", "balance" : 24101.14770458518 }

您可能已經注意到該查詢並未立即執行,而且 MongoDB 花了一兩分鐘的時間來找到該帳戶。在實際應用中,可能會有許多種表現不佳的查詢,您可能無法實際上注意到它們的表現不佳。

您可以配置 MongoDB 來幫助您找出哪些查詢花費的時間比預期的時間長。要做到這一點,首先執行以下命令啟用分析器:

  1. db.setProfilingLevel(1, { slowms: 100 })

setProfilingLevel() 方法接受兩個參數。第一個是分析水平,可以是 012

  • 0 關閉分析器
  • 1 僅在滿足慢查詢條件時啟用分析器
  • 2 啟用所有查詢的分析器

在這個例子中,分析器將分析運行時間超過100毫秒的查詢,這是由第二個參數 { slowms: 100 } 定義的。

注意:使用分析器會降低性能,因為 MongoDB 現在必須分析查詢並執行它們。在監控性能瓶頸時,應該節制使用它。

可以進一步定制分析器將記錄的查詢子集,方法是配置它僅分析某一百分比的查詢,或者按查詢類型進行篩選。要了解如何更好地控制分析器,請參閱有關此主題的 官方文檔

此方法將返回成功消息:

Output
{ "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }

從現在開始,將啟用數據庫分析,並且 MongoDB 將主動監視您執行的每個查詢,以查找需要超過100毫秒完成的查詢。

嘗試執行幾個不同的查詢來試試。首先,使用 count 命令查找 accounts 集合中的文檔數量:

  1. db.accounts.count()

此命令將快速返回集合中的文檔數量:

Output
1020000

然後,試著查找集合中出現的前三個銀行帳戶:

  1. db.accounts.find().limit(3)

同樣地,數據庫將迅速返回結果:

Output
{ "_id" : ObjectId("61ef40640f2ba52efc56ee17"), "number" : "1000-1", "currency" : "EUR", "balance" : 25393.132960293842 } { "_id" : ObjectId("61ef40640f2ba52efc56ee18"), "number" : "1000-2", "currency" : "EUR", "balance" : 63629.42056192393 } { "_id" : ObjectId("61ef40640f2ba52efc56ee19"), "number" : "1000-3", "currency" : "EUR", "balance" : 75602.12331602155 }

最後,再次運行對特定銀行帳戶的搜索查詢:

  1. db.accounts.find({"number": "1000-20"})

此查询将返回结果,但与以前一样,操作将比以前的操作花费更长的时间:

Output
{ "_id" : ObjectId("61a38fd5eedf737ac8e54e96"), "number" : "1000-20", "currency" : "EUR", "balance" : 24101.14770458518 }

即使查询明显较慢,分析器也不会产生任何输出。相反,关于慢操作的详细信息将在数据库内的名为system.profile的特殊集合中注册。该集合是一个大小永远不会超过1 MB的有限集合。这意味着它将始终包含仅最近的慢查询列表。

要检索由分析器识别的查询的信息,您必须以类似这样的方式查询system.profile集合:

  1. db.system.profile.find().sort({ "ts" : -1 }).pretty()

此查询使用find()方法,与往常一样。它还包括一个包含{ "ts" : -1 }作为参数的sort子句。这将以最新的查询为首对结果集进行排序。最后,在末尾使用pretty()方法将以更易读的格式显示输出。

每个慢查询都表示为常规文档,而system.profile则像任何常规集合一样。这意味着您可以过滤结果、对其进行排序,甚至在聚合管道中使用它们以进一步缩小或分析分析器识别的查询列表。

请注意,结果仅由一个文档组成。另外两个查询执行得足够快,不会触发分析器:

Output
{ "op" : "query", "ns" : "test.accounts", "command" : { "find" : "accounts", "filter" : { "number" : "1000-20" }, . . . }, "nreturned" : 1, "keysExamined" : 0, "docsExamined" : 1030000, . . . "millis" : 434, "planSummary" : "COLLSCAN", . . . }

此输出提供了关于慢查询执行的许多细节:

  • op 鍵顯示此信息代表的操作類型。這裡,它是一個 query,因為它代表了一個使用 find() 從數據庫檢索數據的操作。
  • ns 鍵指示了操作涉及的數據庫和集合。如輸出所示,此操作查詢了 test 數據庫中的 accounts 集合。
  • command 鍵提供了有關查詢本身的更多信息。在這種情況下,filter 子鍵包含整個過濾文檔。使用從 opcommand 字段得到的信息,您可以重建相應的查詢。
  • millis 字段中,您將找到完成查詢所需的確切時間。在此示例中,接近半秒。
  • docsExamined 字段提供了掃描文檔以返回結果集的數量。
  • nreturned 表示查詢返回的文檔數量。在此示例中,超過一百萬個掃描的文檔中僅返回了一個文檔。
  • planSummary 顯示了 MongoDB 用於執行查詢的方法。 COLLSCAN 對應於完整的集合掃描,這意味著它逐個瀏覽集合中的每個文檔以查找匹配的銀行帳戶。

所有这些信息都強調了需要一個索引,這個索引可以幫助MongoDB更快地執行這個查詢。數據庫需要查看整個集合才能找到單個文檔,這一點可以從被檢查和返回的文檔數量之間的巨大差異以及執行策略中得到證實。

在這個特定的例子中,創建一個支持根據 number 字段篩選數據的索引將立即提高此類查詢的性能。在實際情況中,解決慢查詢的方案可能有所不同,並且取決於造成問題的具體查詢。

要完成分析會話,您可以通過將分析器級別設置為零來禁用分析器:

  1. db.setProfilingLevel(0)

操作將成功,並顯示確認消息:

Output
{ "was" : 1, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }

現在數據庫恢復到正常運行,不再進行幕後分析。

每當您懷疑慢查詢可能對數據庫的性能產生負面影響時,您都可以使用數據庫分析器來查找它們,並更好地了解它們的結構以及它們是如何執行的。有了這些信息,您將更好地能夠調整它們並改善它們的性能。

結論

通過遵循這個指南,你學會了如何查找 MongoDB 的伺服器統計資料,以及如何使用診斷工具如 mongotopmongostat,以及 MongoDB 的資料庫分析器機制。你可以利用這些工具來更好地了解你的資料庫工作負載,確定哪些集合是最活躍的,以及伺服器主要執行的是寫入還是讀取操作。你還可以識別影響 MongoDB 效能的慢查詢,以便用更有效率的查詢替換它們。

這些只是你可以用來監控 MongoDB 安裝的健康狀況和效能的一部分工具和技術。這些工具中的每一個都可以進一步配置和定制,以提供更有針對性的對伺服器性能的洞察力。我們鼓勵你閱讀 官方 MongoDB 文件,以了解更多關於你可以用來監控伺服器性能並針對其採取行動的技術。

Source:
https://www.digitalocean.com/community/tutorials/how-to-monitor-mongodb-s-performance