持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
在实际开发中,有的时候需要对开发和操作 MongoDB 的应用进行性能分析,从而进一步对性能进行优化。本实验将会讲解一些 MongoDB 中常见的性能优化方案,比如:索引查询优化、数据库设计优化等。
MongoDB Profiler
我们都知道在 MySQL 数据库中有个慢查询日志,它可以帮助我们进行 SQL 语句的优化,提高系统的稳定性和流畅性。同样在 MongoDB 数据库中也有类似的功能,它就是 MongoDB Profiler。我们可以通过它来记录一些超过阈值的查询,后面就可以根据这些超过阈值的记录进行相应的优化(下文将超过阈值的查询简称为“慢查询”)。
MongoDB 中的慢查询记录存储在 system.profile 中,默认情况是关闭的。如果想开启,可以通过 db.setProfilingLevel(level) 进行配置(也可以直接在 MongoDB 配置文件中进行配置)。其中 level 的值如下表所示:
| 状态码 | 描述 |
|---|---|
| 0 | 表示关闭慢查询,默认值。 |
| 1 | 收集超过阈值的查询。 |
| 2 | 为所有的数据库开启慢查询记录,收集所有的数据。 |
➡️ 启用慢查询可以有两种方式:
-
使用 MongoDB 交互式客户端使用命令启用(即 MongoDB shell)
a. 给所有的数据库开启慢查询记录。
db.setProfilingLevel(2)b. 给数据库
lanqiao开启慢查询,并指定阈值,如果查询超过 20 毫秒就需要被记录。use test db.setProfilingLevel(1,{slowms:20})c. 给数据库
lanqiao设置随机采集慢查询的百分比值,采集 42% 的内容。db.setProfilingLevel(1,{sampleRate:0.42})✨ 说明:
sampleRate默认为 1,表示全部采集;上面设置的 0.42 表示只采集 42% 的内容。 -
在 MongoDB 的
mongod.conf配置文件中进行配置a. 用
=号的常规格式配置。profile=1 slowms=20✨ 说明:
profile设置开启慢查询的级别,slowms设置阈值。b. 用
YAML配置文件格式配置。operationProfiling: mode: <string> slowOpThresholdMs: <int> slowOpSampleRate: <double>✨ 说明:
mode:设置开启慢查询的级别,可选值 off、slowOp(对应上面的等级 1)、all(对应上面的等级 2),默认为 off。slowOpThresholdMs:设置阈值,默认值为 100,单位毫秒。slowOpSampleRate: 设置随机采集慢查询的百分比值,sampleRate 值默认为 1,表示都采集,0.42 表示采集 42% 的内容。
➡️ 查看慢查询的记录: 可以使用 db.system.profile.find() 命令查看。
-
查看最近的 5 个慢查询日志
db.system.profile.find().limit(5).sort({ts:-1}).pretty()✨ 说明:
ts指的是命令执行的时间。 -
查看数据库
lanqiao中集合为course的日志db.system.profile.find({ns:'lanqiao.course'}).pretty()✨ 说明:
ns指的是操作的数据库和集合。 -
查询低于 5 毫秒的日志
db.system.profile.find({millis:{$gt:5}}).pretty()✨ 说明:
millis指的是从 MongoDB 操作开始到结束耗费的时间。
➡️ 关闭慢查询:db.setProfilingLevel(0)。
查询优化
查询,我们可以进行哪些优化。
- 避免一些低效率的操作符,比如下表中的操作符:
| 操作符 | 说明 |
|---|---|
$where 和 $exits | 这两个操作符不能使用索引。 |
$ne | 此操作符用于取反操作,而一般来说取反操作效率比较低。因为它必须查看所有的索引条目,此时就不得不扫描整个索引。 |
| $not | 有时候可以使用索引,但是通常情况下不知道如何使用索引,所以大多数情况下 $not 还是会执行全表扫描。 |
$nin | 此操作符总是会全表扫描。 |
-
OR 查询
$or可以对每个语句都适用索引,因为$or实际上是执行两次查询然后将结果合并。通常来说,使用 or 查询多次再合并结果,不如单次查询的效率高。对于单个字段,应该使用$in。 -
创建索引
索引是一个很重要的东西,有了正确的索引,MongoDB 就可以为应用程序提供快速的查询。但不是索引越多越好,有时候错误的使用索引反而会产生慢查询。因为使用索引需要进行两次查找:一次查找索引条目,一次根据索引指针去查找相应的文档。而全表扫描只需要进行一次查询。假如现在是最坏的情况,使用索引进行查找次数会是全表扫描的两倍,此时效率就明显比全表扫描低。
并没有一个严格的规定说,什么时候索引很有用,我们可以根据慢查询或者一些其他的查询分析,来判断索引的使用。
-
MongoDB 查询优化器
MongoDB 的查询计划会将多个索引并行的去执行,最早返回 100 个结果的就是胜者,其他查询计划都会被终止。
数据库设计优化
实际开发中,在数据库的设计阶段,就需要明确集合用途,这对性能调优非常重要。根据集合中数据最常用的操作,对于频繁更新和频繁查询的集合,我们最需要关注的重点是他们的范式化程度
✨ 说明:范式是为了消除重复数据减少冗余数据,从而让数据库内的数据更好的组织,让磁盘空间得到更有效利用的一种标准化标准,满足高等级的范式的先决条件是满足低等级范式
-
数据库的设计优化
- 范式化设计
- 反范式化设计
- 范式化和反范式化设计