mongodb 慢查询与优化

MongoDB 的 Profiler 类似MySQL的 SlowLog和GeneralLog 的结合,设置不同的Profiling级别可以记录不同的操作记录。开启Profiling会对数据库性能造成一定的损耗占用一定的磁盘空间,设置的Profiling级别越高,资源消耗越大。

[TOC]

Profiling

Profiling级别

Profiling级别 描述 备注
0 禁用Profiling 默认级别
1 只记录执行时长超过slowms或符合filter过滤规则的命令 类似mysql的 SlowLog
2 记录所有的操作 类似mysql的 GeneralLog

Profiling的作用域

  • slowms和sampleRate的配置是全局配置,会影响所有的database。slowms慢日志阈值也会作用于diagnostic log
  • 通过 命令行参数或配置文件 指定Profiling级别或filter过滤规则会影响整个实例的所有database
  • 通过 db.setProfilingLevel() 启用并设置Profiling级别,还有Profiling的filter过滤规则只影响当前连接的database
  • 无法在mongos上面启用Profiling,在mongos上设置slowms和sampleRate只会影响diagnostic log
  • 对于Secondary成员,在应用的oplog条目执行时间超过慢日志阈值时,操作会被记录到diagnostic诊断日志中,但是不会被Profiler捕获

操作 Profiling

  • 准备测试数据,创建2个库
use db1;
db.aaa.insert({"name":"sam"});

use db2;
db.aaa.insert({"name":"joy"});
  • 查询Profiling状态,其中 was: 0不开启/1记录慢查询日志/2记录所有查询日志,slowms: 记录慢日志的阈值,默认100ms
PRIMARY> use db1;
PRIMARY> db.getProfilingStatus()
{ was: 1, slowms: 100, sampleRate: 1, ok: 1 }
  • 当前数据 启用Profiling
//.先切换上下文
use db1;

//.为当前数据启用Profiling并设置慢日志阈值为2s,默认100ms
db.setProfilingLevel( 1, { slowms: 2000 } )

//.配置慢日志记录的随机采样率,默认为1即采样率100%
db.setProfilingLevel( 1, { sampleRate: 0.5 } )

//.设置慢日志过滤器filter,只记录执行时间超过2s的query操作
db.setProfilingLevel( 2, { filter: { op: "query", millis: { $gt: 2000 } } } )
  • 当前数据库 关闭Profiling
//.先切换上下文
use db1;

//.为当前数据库关闭Profiling
db.setProfilingLevel(0)
  • 通过 命令行 全局配置 Profiling
mongod --profile 1 --slowms 2000 --slowOpSampleRate 0.5
  • 通过 配置文件 全局配置 Profiling
[root@localhost ~]# cat /data/mongodb-4.0.25/mongod.conf | grep -A 4 "operationProfiling"
operationProfiling:
   mode: slowOp
   slowOpThresholdMs: 2000
   slowOpSampleRate: 0.5
   filter: '{ op: "query", millis: { $gt: 2000 } }'

查看慢日志内容

//.获取最近10条慢日志记录
db.system.profile.find().limit(10).sort({ts:-1}).pretty()

//.返回除command命令之外的所有慢日志
db.system.profile.find({op:{$ne:'command'}}).pretty()

//.返回某个集合的慢日志
db.system.profile.find({ns:'db1.aaa'}).pretty()

//.返回超过5ms的慢日志
db.system.profile.find({millis:{$gt:5}}).pretty()

//.返回某个时间段内的慢日志
db.system.profile.find( {
   ts : {
      $gt: new ISODate("2024-07-12T03:00:00Z"),
      $lt: new ISODate("2024-07-12T03:40:00Z")
   }
}, { user: 0 } ).sort( { millis: -1 } )

//.显示5个最近的事件
show profile

修改system.profile大小

  • system.profile 为一个默认只有 1MB 的capped集合,通常只能容纳上千条记录。修改system.profile容量的操作如下:
  • 在Primary实例上:先关闭,删除并重建system.profile,再开启
//.1.关闭Profiling
db.setProfilingLevel(0);

//.2.删除system.profile集合
db.system.profile.drop();

//.3.创建system.profile集合
db.createCollection("system.profile", {capped:true, size:4000000});

//.4.再次开启Profiling
db.setProfilingLevel(1, {slowms:2000});

//.确认大小
db.system.profile.stats().size;
  • 对于Seconary实例:必须先将其踢出副本集,将其作为单实例,然后执行上述修改操作,之后再将其加入到副本集

针对慢查询的优化

针对慢查询的优化,步骤通常如下:

  • 1.先通过慢查询日志(system.profile)找到超过阈值的语句,比如 500ms
  • 2.再通过 .explain() 解析影响行数,分析为什么超过 500ms
  • 3.评估是否添加索引
Copyright © www.sqlfans.cn 2024 All Right Reserved更新时间: 2025-01-03 13:00:02

results matching ""

    No results matching ""