如何快速定位MongoDB分片集群中的慢查询节点_利用System.profile定位到具体Shard

作者:袖梨 2026-06-30
mongos上查不到慢查询是因为其仅路由请求而不执行查询,profile日志实际存储在各shard的mongod中;需通过sh.status()定位shard,直连对应mongod并为system.profile创建ts索引,调低slowms阈值,重点分析docsExamined与nreturned比值及planSummary识别广播查询。

在分片集群里查慢查询,system.profile 只存在于各 mongod shard 节点上,mongos 上查不到——这不是配置错了,是设计如此。

为什么 mongos 上执行 db.setProfilingLevel() 没反应

mongos 不执行任何查询逻辑,只做路由和结果合并。调用 db.setProfilingLevel() 后返回 {"ok": 0, "errmsg": "no profiling information available"} 是正常现象,不是权限或连接问题。

  • 所有实际查询执行都发生在后端 mongod 实例(即每个 shard)上,profile 数据只会写入对应节点的 system.profile
  • config server 和 mongossystem.profile 均为空或不可用,连上去也查不到业务查询记录
  • 别在 mongos 上浪费时间建索引或调阈值,它根本不会写 profile

怎么快速定位到具体哪个 shard 节点要查

先确认查询到底打到了哪些 shard,再挨个连过去查。不能靠猜,也不能只看负载高就直奔 primary。

  • mongos 上运行 sh.status(),重点看目标集合的 chunks 分布和 shards 列表,记下 host 字符串(如 shard02/10.0.1.20:27018,10.0.1.21:27018
  • db.getSiblingDB("config").shards.find() 拿到每个 shard 的完整地址列表,挑出你怀疑的节点(比如日志里频繁出现 "planSummary":"SHARD_MERGE" 的那个)
  • 直连时优先选 secondary 节点:mongo --host 10.0.1.21:27018 -u user -p pwd --authenticationDatabase admin,避免在 primary 上加额外压力

连上 shard 后必须做的三件事

刚连上别急着 find,不处理这三项,查起来要么慢、要么漏、要么压根找不到。

  • 立即建索引:db.system.profile.createIndex({ ts: -1 }),否则 find({millis: {$gte: 50}}).sort({ts: -1}) 会全表扫描,几秒变几十秒
  • 调低 slowmsdb.setProfilingLevel(1, {slowms: 50}),分片环境下单个 shard 执行可能只有 10–20ms,但叠加网络、合并后总耗时超 300ms,不调低就记录不到
  • 查完立刻验证是否生效:db.getProfilingStatus() 返回 "was": 1"slowms": 50,才算真正启用

查出来以后怎么看才不被误导

别只盯着 millis 数值。一个 320ms 的请求在 mongos 日志里出现,但在 shard 的 system.profile 里可能只看到几个 millis: 7 的记录——这是正常的,因为 shard 只记自己干的那部分活。

  • 重点筛 docsExamined > nreturned * 10 的记录,比如 docsExamined: 50000, nreturned: 25,说明索引没走或者失效
  • planSummary:出现 "COLLSCAN""IXSCAN"keysExamined: 0,基本等于没索引
  • 对疑似语句补 explain("executionStats") 复现,特别注意 shards 字段下是否列出了多个节点——如果是,说明触发了广播查询,大概率缺分片键

最容易被忽略的是:profile 数据默认只保留最近 1MB 或 30 分钟(取决于 capped size),等出问题再开 profiler,早就覆盖掉了。得提前在关键 shard 上常驻开启,并定期检查索引是否还在。

相关文章

精彩推荐