在MongoDB 6.0中定位性能瓶颈,需在admin库执行db.setProfilingLevel(2, {slowms: 100})启用慢查询日志,通过db.system.profile.find或聚合管道筛选COLLSCAN且millis>100的查询,并可导出分析或清理日志。

在MongoDB 6.0中定位性能瓶颈,需主动捕获执行时长超阈值且触发全表扫描(COLLSCAN)的查询,这要求精确配置慢查询日志级别、启用统计采集,并过滤出真正未走索引的扫描操作。
启用数据库级慢查询日志并设置阈值
连接到目标数据库后,执行 db.setProfilingLevel(2, { slowms: 100 }),将分析器设为详细模式,仅记录执行时间 ≥100ms 的操作。该设置会立即生效,无需重启服务,但【必须在admin库下执行】,否则报错“not authorized on admin to execute command”。
若当前用户无admin库权限,先用具有clusterAdmin角色的账号登录再操作。
确认全表扫描查询被实际记录
执行一条明确触发 COLLSCAN 的查询验证日志是否捕获:例如在 orders 集合无索引字段 status 上运行 db.orders.find({ status: "pending" })。等待其执行超100ms后,检查系统集合:db.system.profile.find({ "executionStats.executionStages.stage": "COLLSCAN" }).limit(1).pretty()。
如果返回空,说明该次查询未达 slowms 阈值或未命中 profiling 级别2的记录条件;此时可临时调低 slowms 至 0(仅调试用),但【切勿在生产环境长期设为0】,否则磁盘I/O和存储增长不可控。
从system.profile中提取全表扫描慢查询
方法一:基础筛选
db.system.profile.find({ "executionStats.executionStages.stage": "COLLSCAN", "millis": { $gt: 100 } }, { ts: 1, op: 1, ns: 1, millis: 1, query: 1, "executionStats.nReturned": 1 }).sort({ ts: -1 }).limit(5)
方法二:精准排除索引扫描干扰
全表扫描可能混杂在 IXSCAN 后的嵌套结构里,必须递归检查 executionStages 是否存在顶层 COLLSCAN。使用聚合管道确保不漏判:
db.system.profile.aggregate([
{ $match: { "millis": { $gt: 100 }, "executionStats.executionStages.stage": "COLLSCAN" } },
{ $addFields: { hasCollscan: { $eq: [ "$executionStats.executionStages.stage", "COLLSCAN" ] } } },
{ $match: { hasCollscan: true } },
{ $project: { ts: 1, ns: 1, query: 1, millis: 1, "executionStats.nReturned": 1, "executionStats.executionTimeMillis": 1 } }
])
方法三:导出为JSON便于分析
在mongo shell中执行上述聚合后,加 .forEach(printjson) 直接输出可读格式;如需保存,用 mongodump 导出 system.profile 集合:mongodump --db your_db_name --collection system.profile --query '{"millis": {"$gt": 100}, "executionStats.executionStages.stage": "COLLSCAN"}' -o /tmp/profile_dump。
关闭分析器并清理历史日志(可选)
第一步:停用 profiling,避免持续写入影响性能 → 执行 db.setProfilingLevel(0)。
第二步:清空旧 profile 记录 → db.system.profile.drop()。该操作不可逆,执行前确认已导出所需数据。
第三步:若需保留部分记录,可用 db.system.profile.remove({ ts: { $lt: ISODate("2024-01-01T00:00:00Z") } }) 删除过期条目。


















