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

为什么在 mongos 上查不到慢查询?
因为 mongos 只做请求路由,不执行实际查询逻辑,所以直接在 mongos 上运行 db.setProfilingLevel() 完全无效——system.profile 根本不会写入任何记录。你看到的“慢查询”日志,其实都藏在后端每个 shard 节点(即独立的 mongod 实例)里。
怎么定位到具体哪个 shard 的 profile?
先确认分片分布和当前活跃 shard:
- 连上
mongos,运行sh.status(),看shards列表和各集合的分片键范围 - 用
db.getSiblingDB("config").shards.find()查所有 shard 的 host 地址(形如shard01/10.0.1.10:27018,10.0.1.11:27018) - 挑出疑似负载高的 shard,用
mongo --host 10.0.1.10:27018 -u user -p pwd --authenticationDatabase admin直连该mongod
注意:不能只连 primary;如果该 shard 是副本集,最好连 secondaryOk 节点查 system.profile,避免干扰主节点负载。
查 profile 时最容易忽略的三件事
system.profile 是固定集合,默认不建索引,查起来极慢:
- 必须手动加索引:
db.system.profile.createIndex({ ts: -1 }),否则find({millis: {$gte: 500}}).sort({ts: -1})会全表扫描 - 默认
slowms是 100ms,分片环境下建议调低:db.setProfilingLevel(1, {slowms: 50}),否则小延迟叠加后总耗时超阈值,单个 shard 却不记录 - 常见错觉:mongos 日志里显示某查询耗时 320ms,但去所有 shard 的
system.profile都找不到对应记录——这是因为 mongos 记的是端到端时间(含网络、协调、结果合并),而 shard 只记自己执行那部分(可能只有 8ms)
怎么快速筛出真正有问题的慢操作?
别只盯着 millis,重点看执行效率指标:
- 查
docsExamined > nreturned * 10的记录,说明大量文档被扫描却没返回,大概率没走对索引 - 匹配
planSummary: "COLLSCAN"或"IXSCAN" + keysExamined: 0,代表索引失效或缺失 - 用
db.system.profile.find({op: "query", "docsExamined": {$gt: 10000}}).limit(5)快速抓大头 - 配合
explain("executionStats")对应语句复现,确认是否因分片键缺失导致广播(比如查{status: "done"}却没带分片键,就会扫所有 shard)
真正卡住分片集群的,往往不是单条慢 query,而是没带分片键的广播查询——它让 1 个请求变成 N 个全量扫描,且 profile 里每条都看起来“不慢”,但 mongos 日志里总耗时爆炸。这点最容易被忽略。


















