MongoDB 数据库分析器配置与使用

警告:数据库分析器可能降低 MongoDB 性能。启用前,可先考虑 Atlas Query Profiler、Atlas Performance Advisor 或 $queryStats 聚合阶段。性能影响见下文“分析器开销”。

数据库分析器收集运行中 mongod 所执行命令的详细信息,包括 CRUD、配置与管理命令,并将数据写入各数据库的固定大小集合 system.profile。

分析器默认关闭,可以按数据库或整个实例启用,并选择不同级别。启用会影响性能与磁盘使用。输出文档、Profile 命令和 db.currentOp() 可提供更多参考。

分析级别

  • 0:关闭,不收集数据,默认值。
  • 1:收集超过 slowms 阈值或匹配指定 filter 的操作。设置 filter 后,分析器不再使用 slowms 与 sampleRate,只捕获匹配操作。
  • 2:收集全部操作,忽略用户提供的 slowms 与 filter。

启用与配置

mongod 支持分析器。启动时可在配置文件设置 operationProfiling.mode;运行期间可用 mongosh 的 db.setProfilingLevel();驱动也可调用对应方法。

为数据库启用后,MongoDB 会创建 system.profile。下面为当前连接数据库的所有操作启用分析:

db.setProfilingLevel(2)

返回值的 was 表示此前级别,ok:1 表示成功:

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

新设置可通过下文的方法查看。从 MongoDB 5.0 起,通过 profile 或 db.setProfilingLevel() 修改级别、slowms、sampleRate、filter,都会记入日志。

全局与数据库级设置

slowms 和 sampleRate 是全局设置,影响进程内所有数据库。通过 profile 或 shell 方法设置的级别与 filter 仅作用于当前数据库;通过启动参数或配置文件设置时,作用于整个进程。

慢操作阈值

默认阈值为 100 毫秒。慢操作依据 workingMillis 判断,即 MongoDB 实际处理该操作的时间,等待锁与流控等时间不会影响是否超阈值。

可通过 profile/db.setProfilingLevel() 的 slowms、启动参数 –slowms,或配置文件 slowOpThresholdMs 修改。

下面把当前数据库设为级别 1,并将实例阈值设为 20 毫秒:

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

级别 1 会记录慢于阈值的操作。

重要:阈值影响 mongod 的所有数据库,数据库分析器与诊断日志都使用它。应设为仍然有用的尽可能高的值,避免性能下降。

mongos 可用同一方法配置 slowms 和 sampleRate,但因为没有分析器,只影响诊断日志。[1] 例如设置 20 毫秒:

db.setProfilingLevel( 0, { slowms: 20 } )

读写操作的分析记录和诊断日志包含 planCacheShapeHash,用于识别计划缓存查询形状相同的慢查询。从 MongoDB 8.0 起,原 queryHash 值也写入这个新字段;旧版本只有 queryHash,未来版本将移除已弃用字段。

另外,planCacheKey 提供慢查询的计划缓存信息。

从节点会把应用耗时超过阈值的 oplog 项写入诊断日志,归于 REPL,形式为 applied op: <oplog entry> took <num>ms。它不受系统/组件日志级别或分析级别影响,但受 slowOpSampleRate 影响。分析器不捕获这些慢 oplog 项。

随机采样慢操作

可以只记录慢操作的随机子集:[2]

  • 通过 profile 或 db.setProfilingLevel() 设置 sampleRate。
  • mongod 或 mongos 启动时指定 –slowOpSampleRate。
  • 在配置文件设置 slowOpSampleRate。

默认 1.0,记录全部慢操作。设为 0 到 1 之间时,级别 1 的数据库按该比例随机采样。下面采样 42%:

db.setProfilingLevel( 1, { sampleRate: 0.42 } )

这个采样率也影响系统日志。mongos 中只影响诊断日志,[1] 例如:

db.setProfilingLevel( 0, { sampleRate: 0.42 } )

重要:logLevel=0 时,诊断日志按 slowOpSampleRate 记录慢操作;更高日志级别记录所有操作,无论耗时。例外是从节点的 oplog 日志:仍只记录慢项,提高 logLevel 不会记录全部 oplog。

[1] 另见下文“分析与分片”。

通过过滤器选择操作

可通过 profile、db.setProfilingLevel() 或配置文件设置 filter。mongod 上同时影响诊断日志和已启用的分析器;mongos 上仅影响日志。

注意:设置 filter 后,slowms 与 sampleRate 都不再影响诊断日志或分析器。

下面把当前数据库设为级别 1,只记录耗时超过两秒的 query:

db.setProfilingLevel( 1, { filter: { op: "query", millis: { $gt: 2000 } } } )

查看级别

db.getProfilingStatus()

返回类似:

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

was 是当前级别;slowms 是毫秒阈值;sampleRate 是慢操作采样比例。

关闭分析器

db.setProfilingLevel(0)

关闭可以改善性能、降低磁盘使用。

对整个 mongod 启用

在开发和测试环境,可对实例所有数据库启用:

mongod --profile 1 --slowms 15 --slowOpSampleRate 0.5

也可以在配置文件设置 operationProfiling。这会启用级别 1,把超过 15 毫秒的操作视为慢操作,并采样其中 50%。[2]

logLevel=0 时,slowms 与 slowOpSampleRate 也影响诊断日志;mongos 也支持这两个日志设置。相关选项为 mode、slowOpThresholdMs 和 slowOpSampleRate。

分析与分片

mongos 无法启用分析器。分片集群需要在每个 mongod 上分别启用。不过,可在 mongos 设置 –slowms 和 slowOpSampleRate,配置慢操作诊断日志。

查看分析数据

查询 system.profile 即可查看。输出字段见数据库分析器输出文档。事务内部不能对 system.profile 执行任何操作,包括读取。

查询示例

最近十条记录:

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

排除 command($cmd)操作:

db.system.profile.find( { op: { $ne : 'command' } } ).pretty()

只看 mydb.test:

db.system.profile.find( { ns : 'mydb.test' } ).pretty()

耗时超过五毫秒:

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

指定时间范围、隐藏 user 字段,并按耗时排序:

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

最近五个事件

对已启用分析的数据库,mongosh 的 show profile 显示最近五个执行至少一毫秒的操作:

show profile

分析器开销

启用会影响数据库性能,级别 2 或级别 1 配很低阈值时尤其明显。数据还写入 system.profile 和 MongoDB 日志,增加磁盘消耗。

警告:生产环境启用前,先考虑性能与存储影响。

system.profile 集合

这是默认大小为 1 MB 的固定大小集合,通常可容纳几千条记录,但每项操作产生的数据量因应用而异。

调整主节点上的大小

依次关闭分析器、删除 system.profile、创建新集合,再重新启用。例如创建 4,000,000 字节的集合:

db.setProfilingLevel(0)

db.system.profile.drop()

db.createCollection( "system.profile", { capped: true, size:4000000 } )

db.setProfilingLevel(1)

调整从节点上的大小

必须先停止从节点,以独立实例运行,再执行相同步骤。完成后,重新作为副本集成员启动。详情见自托管副本集成员维护指南。

[2] 从节点记录应用时间超过阈值的 oplog 项:写入诊断日志的 REPL 组件,使用 applied op 形式,不依赖日志级别或分析级别,受 slowOpSampleRate 影响。分析器不会捕获慢 oplog 项。


原文:Database Profiler。作者/维护者:MongoDB 文档团队。本文为原文的中文译文;代码保留原文内容。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容