警告:数据库分析器可能降低 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 文档团队。本文为原文的中文译文;代码保留原文内容。











暂无评论内容