开启MongoDB慢查询日志需配置slowms阈值(如100ms)并启用profiling模式1;Python可通过正则解析日志或查询system.profile集合获取慢操作,再用explain('executionStats')分析执行计划定位性能瓶颈。

怎么开启MongoDB的慢查询日志?
默认情况下,MongoDB不记录慢查询,必须手动启用。关键参数是 slowms,它定义“慢”的阈值(单位毫秒),配合 logLevel 和日志路径才能生效。
- 在配置文件(如
/etc/mongod.conf)中添加:operationProfiling: mode: slowOp slowms: 100
——表示耗时超过 100ms 的操作被记录 - 如果用命令行启动,加参数:
--profile 1 --slowms 100;注意--profile值为 1 表示只记录慢操作,2 表示记录所有操作(慎用,IO 和磁盘压力大) - 日志输出位置取决于
systemLog.path配置;若没设,可能打到 stdout 或系统日志,查不到就先确认日志路径是否可写
Python里怎么读取和解析慢查询日志?
日志是文本格式,但结构松散,直接用 grep 或正则提取最实际。不要试图用 JSON 解析器硬读——MongoDB 日志不是标准 JSON,时间戳、线程 ID、命令字段之间没有严格分隔。
- 典型慢日志行示例:
2024-05-22T10:32:14.123+0000 I COMMAND [conn123] query mydb.users planSummary: COLLSCAN keysExamined:0 docsExamined:12456 nreturned:10 reslen:2456 124ms - 推荐用 Python 正则快速提取关键字段:
import re pattern = r'(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3})\s+\w+\s+\w+\s+\[(\w+)\]\s+(\w+)\s+(\w+)\.(\w+)\s+.*?(\d+)ms' for line in open('/var/log/mongodb/mongod.log'): m = re.search(pattern, line) if m: ts, conn, op, db, coll, duration = m.groups() # 这里就可以存入本地 CSV 或发到监控系统 - 注意:日志中同一查询可能跨多行(比如带
query:或planSummary:的详细信息),只抓首行即可,避免重复计数
如何用Python连接profiling collection查慢操作?
MongoDB 的 system.profile 是一个 capped collection,记录最近的 profiling 数据(前提是启用了 profiling)。比解析日志更结构化,但默认不开启,且有性能开销。
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
- 启用 profiling(需有
dbAdmin权限):db.setProfilingLevel(1, { slowms: 100 });level 1 记慢操作,level 2 记全部 - Python 查询示例:
from pymongo import MongoClient client = MongoClient('mongodb://localhost:27017/') db = client['mydb'] profile_docs = list(db.system.profile.find( {'millis': {'$gt': 100}}, {'ts': 1, 'op': 1, 'ns': 1, 'query': 1, 'millis': 1, '_id': 0} ).limit(10)) - ⚠️ 注意:
system.profile是 capped collection,容量有限(默认 1MB),老数据会被自动覆盖;不能长期依赖它做归档,只适合临时排查 - 字段说明:
ns是数据库名.集合名,query是原始查询条件(可能被截断),millis是执行耗时
为什么用 explain() 分析单个慢查询?
日志和 profiling 只告诉你“谁慢”,但不解释“为什么慢”。这时候必须对具体查询调用 explain(),看执行计划是否走了索引、是否发生内存排序、是否扫描了过多文档。
立即学习“Python免费学习笔记(深入)”;
- 在 Python 中对慢查询复现并分析:
collection = db.users result = collection.find({'status': 'active', 'created_at': {'$lt': datetime(2023,1,1)}}) explain_result = collection.find({'status': 'active', 'created_at': {'$lt': datetime(2023,1,1)}}).explain() - 重点看
executionStats.nReturned(返回多少)、executionStats.totalDocsExamined(扫描多少)、executionStats.executionTimeMillis(真实耗时) - 常见陷阱:
explain()默认是queryPlanner模式,不包含实际执行统计;要加executionStats级别:.explain('executionStats') - 如果
totalDocsExamined远大于nReturned,大概率缺索引;如果出现stage: "SORT"且memUsage很高,说明排序没走索引,可能触发内存限制报错QueryExceededMemoryLimitNoDiskUseAllowed
真正卡住人的,往往不是找不到慢查询,而是把日志里的一行 124ms 和线上用户抱怨的“点一下卡三秒”对不上号——因为慢查询可能是聚合链路中某一步、或是带事务的复合操作。别只盯着单条语句,得结合应用层 trace ID 和 MongoDB 日志时间戳交叉比对。

















