如何监视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. }

此代码执行一个循环,连续运行一百万次。每次循环迭代时,它都会在帐户集合上执行一个insertOne()方法来插入一个新文档。在每次迭代中,该方法为number字段赋值,该值由1000-前缀和该迭代的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提供的性能监控工具的测试数据。在下一步中,您将学习如何检查基本的服务器使用统计信息。

步骤2 — 检查服务器使用统计信息

MongoDB自动跟踪多项有用的性能统计信息,定期检查这些信息是监控数据库的基本方式。请注意,这些统计信息不会提供关于数据库当前情况的实时见解,但它们可以用于确定数据库的性能如何以及是否存在任何即将发生的问题。

警告:本指南中概述的MongoDB监控命令会返回有关您的数据库及其性能的潜在敏感信息。因此,其中一些命令需要高级权限。

具体来说,本步骤中概述的serverStatus()方法以及下一步中突出显示的mongostatmongotop命令都需要用户被授予clusterMonitor角色才能运行。同样,第4步中概述的setProfilingLevel()方法需要dbAdmin角色。

假设您已按照如何在Ubuntu 20.04上安全配置MongoDB的先决条件教程,并以在该指南中创建的管理用户连接到MongoDB实例,则需要授予其这些额外的角色才能按照本指南中的示例操作。

首先,切换到您的用户身份验证数据库。在以下示例中,这是admin,但如果不同,请连接到您自己的用户身份验证数据库:

  1. use admin
Output
switched to db admin

然后运行grantRolesToUser()方法,并向您的用户授予clusterMonitor角色以及在创建accounts集合的数据库上授予dbAdmin角色。以下示例假设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 为前缀,货币始终为美元。

在新文档被插入时,检查 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 来监视数据库活动如何分布在不同的集合上,以帮助您更好地理解您的模式并计划扩展。它还提供了关于集合使用是更倾向于读操作还是写操作的见解。

第四步 — 使用 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。这个集合是一个有限制大小的集合,永远不会超过1MB。这意味着它将始终包含仅最近慢查询的列表。

要检索分析器识别的查询的信息,您必须以如下方式查询system.profile集合:

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

这个查询使用了find()方法,像往常一样。它还包括一个sort子句,其中包含{ "ts" : -1 }作为参数。这将以最新查询优先的方式对结果集进行排序。最后,末尾的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