查看 MongoDB 慢查询语句主要依赖数据库分析器(Profiler)或慢查询日志,优化核心在于建立合适索引并分析执行计划。生产环境开启分析器需控制阈值,避免日志量过大影响性能。
先说结论:定位慢查询需开启 Profiler 级别 1 并设置阈值,优化核心是利用 explain 分析执行计划并补充缺失索引。
- 先定位:使用 db.setProfilingLevel 开启慢查询记录
- 先做:针对高频慢查询字段创建复合索引
- 再验证:通过 explain 确认索引命中且扫描行数降低
命令速用版
以下命令可直接在 mongosh 或 mongo shell 中执行,用于快速开启监控和查看慢语句。
// 1. 开启慢查询监控,阈值设为 100 毫秒
db.setProfilingLevel(1, {slowms: 100});
// 2. 查看最近 5 条慢查询记录
db.system.profile.find({millis: {$gt: 100}}).sort({ts: -1}).limit(5);
// 3. 分析特定查询的执行计划
db.collection.find({key: value}).explain("executionStats");为什么会这样
慢查询指执行时间超过设定阈值的操作,常见原因是查询字段缺少索引。当 MongoDB 无法使用索引时,会进行全表扫描(COLLSCAN),随着数据量增加耗时线性增长。通过 Profiler 记录执行时间超过阈值的操作,可以直观定位性能瓶颈。
分步处理
按照以下步骤从开启监控到完成优化,确保每一步都有验证。
1. 开启 Profiler 监控
在生产环境建议使用级别 1,仅记录超过阈值的查询。默认阈值为 100 毫秒,可根据业务容忍度调整。
db.setProfilingLevel(1, {slowms: 100});2. 抓取慢查询语句
慢查询记录存储在 system.profile 集合中,通过查询该集合获取耗时最长的操作。
db.system.profile.find().sort({ts: -1}).limit(10);3. 分析执行计划
使用 explain 命令查看查询是否命中索引,关注 totalDocsExamined 指标。
db.orders.find({userId: 1}).explain("executionStats");4. 创建优化索引
根据查询条件创建复合索引,确保索引字段顺序与查询匹配。
db.orders.createIndex({userId: 1, date: -1});怎么验证是否生效
优化后需再次执行 explain 命令,对比优化前后的关键指标。
- 索引使用情况:executionStats 中的 indexName 应显示具体索引名,而非 null。
- 扫描效率:totalDocsExamined 应接近 nReturned,若远大于返回结果数说明仍有全表扫描。
- 执行时间:executionTimeMillis 应显著低于优化前,但具体数值受负载影响。
常见坑
- 生产环境开启级别 2:级别 2 会记录所有操作,日志量过大可能拖慢数据库,仅建议在调试环境使用。
- 阈值设置过低:阈值设置过低(如 1ms)会导致大量正常查询被记录,增加 I/O 负担。
- 索引过多:过多索引会降低写入性能,应定期清理未使用或效率低下的索引。
- 忽略覆盖查询:若查询字段均在索引中,可构建覆盖查询避免回表,进一步提升性能。
常见问题
默认慢查询阈值是多少?
MongoDB 慢查询默认阈值为 100 毫秒,可通过 slowms 参数调整。
Profiler 有哪几个级别?
共三个级别:0 关闭,1 记录慢查询,2 记录所有操作。
生产环境能开 Profiler 吗?
可以,但建议使用级别 1 并设置较高阈值,避免影响性能。
如何永久配置慢查询日志?
需在 mongod.conf 配置文件中设置 operationProfiling 参数,重启服务生效。
参考来源
- 51CTO 博客:如何有效处理 MongoDB 中的慢查询:识别与优化策略
- CSDN 博客:MongoDB 查询性能调优:诊断慢查询的实用方法
- 技术博客:MongoDB 慢查询优化实战:从 Profiling 到索引优化的完整指南
- MongoDB 官方文档片段:src/mongo/db/query/README_explain.md