签到成功

知道了

CNDBA社区CNDBA社区

MongoDB 4.4 compact 压缩 说明

2022-05-10 09:31 2141 0 原创 MongoDB
作者: dave

1 Compact 命令概述


官网对compact的说明如下:
https://www.mongodb.com/docs/v4.4/reference/command/compact/

compact 以MongoDB 集合为操作对象,重新和整理集合中所有的数据和索引。 对于WiredTiger 引擎,compact命令还会释放不需要的磁盘空间给操作系统。

Compact只能在mongod 实例上运行,不能在mongos实例上执行,对于sharded cluster环境,需要分别在每个shard上执行。 http://www.cndba.cn/cndba/dave/article/107985

在compact 操作完成后,mongod 会并行的重建所有索引。http://www.cndba.cn/cndba/dave/article/107985http://www.cndba.cn/cndba/dave/article/107985

1.1 Compact 命令格式

Compact 语法格式:

use somedb
db.runCommnd({compact: "somecollection"})
db.runCommnd({compact: "somecollection", force: true})

Compact 命令有3个选项:

http://www.cndba.cn/cndba/dave/article/107985

  1. Compact:指定操作集合的名称。
  2. Force:可选项。从MongoDB 4.4 开始改成flag类型,指定该选项后,将在副本集的primary 节点执行命令。在4.4 之前的版本,该选项是布尔型,仅当该选项设置为true时才可以在副本集的primary 节点执行compact 命令,当该选项设置为false时,在primary 执行将报错。 因为该命令会block 所有其他的操作。从4.4 开始,compact 不会block MongoDB 的CRUD操作。在副本集的从库执行时可以不加该选项。
  3. Comment:4.4 版本的新增可选项。该注释会附加到compact命令上,一旦设置,该注释可以会出现在3个位置:
    1) mongod的log日志:attr.command.cursor.comment 列。
    2) database profiler的输出结果的command.comment列。
    3) currentOp 输出结果的command.comment列。

MongoDB 4.4 数据库分析器(Database Profiler)
https://www.cndba.cn/dave/article/107982http://www.cndba.cn/cndba/dave/article/107985

1.2 Compact 的阻塞问题

从4.4 版本开始,在WiredTiger 引擎上执行compact命令,仅block 如下元数据操作,不在block MongoDB CRUD 操作:

  1. db.collection.drop()
  2. db.collection.createIndex() 和db.collection.createIndexes()
  3. db.collection.dropIndex() 和db.collection.dropIndexes()

在4.4 版本之前,compact 命令在压缩时会block 数据库上的所有操作,包括CRUD操作,因为建议在维护窗口内执行compact命令,而从4.4 开始,可以在任意时间执行。http://www.cndba.cn/cndba/dave/article/107985

可以通过mongod的日志文件或者在mongo shell中执行 db.currentOp() 方法来查看compact的进程

1.3 Compact 异常中断处理

如果在compact 操作执行完成之前通过db.killOp()方法或者重启mongod 来终端了compact操作,那么需要关注以下事项:

  1. 如果启用了journaling,那么数据会依然有效并且可用,不用关心compact 操作的状态,可能仅仅需要手工重建一下相关索引。
  2. 如果没有启用journaling,并且在compact 操作进行时终端了mongod或者compact命令,那么无法保证处于有效状态。
  3. 不管是以上的哪一种情况,集合中的大部分空闲空间都将变成不可用状态,因此需要重新执行compact命令来完成压缩,从而重用这些空闲空间。

MongoDB 4.4 中 journal 和 oplog 日志 说明
https://www.cndba.cn/dave/article/107979

1.4 Compact 的磁盘空间

可以通过在compact 之前和之后分别执行collStats命令来查看集合占用的存储空间。

MongoDB 查看 数据库 和 集合 的 大小
https://www.cndba.cn/dave/article/107983

在WiredTiger 引擎中,compact 会尝试减少集合中data和 indexes 占用的存储空间,并释放不需要的磁盘空间给操作系统。当删除了集合中的大量数据后,执行该命令会效果更明显。

1.5 副本集中执行compact命令

在副本集的主库执行Compact命令不会同步到从库,因此需要分别在副本集的每个成员上分别执行。副本集的从库也可以执行compact命令,并且不需要指定force 选项。

从MongoDB 4.4.9和4.2.18 开始,在secondary 节点上执行compact命令时,从库只是变成不可用,不会进入RECOVERING 状态。在之前的版本则是进入RECOVERING 状态。当操作compact 结束,从节点恢复成SECONDARY 状态。

2 操作示例


2.1 主节点操作

查看集合信息:

shard1:PRIMARY> db.user.totalSize()
2109440
shard1:PRIMARY> db.user.totalIndexSize()
1572864
shard1:PRIMARY> db.user.stats()
{
        "ns" : "cndba.user",
        "size" : 1147670,
        "count" : 33755,
        "avgObjSize" : 34,
        "storageSize" : 536576,
        "freeStorageSize" : 0,
        "capped" : false,
……
        "nindexes" : 2,
        "indexBuilds" : [ ],
        "totalIndexSize" : 1572864,
        "totalSize" : 2109440,
        "indexSizes" : {
                "_id_" : 954368,
                "_id_hashed" : 618496
        },
        "scaleFactor" : 1,
……

执行compact,在副本集主库执行,这里提示必须加force 选项:http://www.cndba.cn/cndba/dave/article/107985

shard1:PRIMARY> db.runCommand({compact:"user"})
{
        "ok" : 0,
        "errmsg" : "will not run compact on an active replica set primary as this is a slow blocking operation. use force:true to force",
……
}
shard1:PRIMARY> db.runCommand({compact:"user",force:true})
{
        "bytesFreed" : 0,
        "ok" : 1,
……

查看压缩后的集合大小信息:http://www.cndba.cn/cndba/dave/article/107985

shard1:PRIMARY> db.user.totalSize()
2142208
shard1:PRIMARY> db.user.totalIndexSize()
1593344
shard1:PRIMARY> db.user.stats()
{
        "ns" : "cndba.user",
        "size" : 1147670,
        "count" : 33755,
        "avgObjSize" : 34,
        "storageSize" : 548864,
        "freeStorageSize" : 12288,
        "capped" : false,
……
        "nindexes" : 2,
        "indexBuilds" : [ ],
        "totalIndexSize" : 1593344,
        "totalSize" : 2142208,
        "indexSizes" : {
                "_id_" : 962560,
                "_id_hashed" : 630784
        },
……

因为我们操作之前没有删除文档,所以这里看到文档的大小是有减少,但索引的大小是增加了的。 http://www.cndba.cn/cndba/dave/article/107985

2.2 从节点操作

在从库操作之前,我们先删除文档的内容。 在进行操作。 因为是副本集环境,我们现在主库上进行删除操作。

shard1:PRIMARY> db.user.count()
33755
shard1:PRIMARY>
shard1:PRIMARY> db.user.count()
33755
shard1:PRIMARY> db.user.findOne()
{ "_id" : 44, "name" : "cndba" }
shard1:PRIMARY> db.user.remove({_id:{$gt:10}})
WriteResult({ "nRemoved" : 33753 })
shard1:PRIMARY> db.user.count()
2
shard1:PRIMARY>
shard1:PRIMARY> rs.printSlaveReplicationInfo()
WARNING: printSlaveReplicationInfo is deprecated and may be removed in the next major release. Please use printSecondaryReplicationInfo instead.
source: 172.31.185.120:27018
        syncedTo: Tue May 10 2022 09:07:07 GMT+0800 (CST)
        0 secs (0 hrs) behind the primary
source: 172.31.185.131:27018
        syncedTo: Tue May 10 2022 09:07:07 GMT+0800 (CST)
        0 secs (0 hrs) behind the primary
shard1:PRIMARY>

这里同步正常,我们到从库进行操作。

shard1:SECONDARY> rs.secondaryOk()
shard1:SECONDARY> db.user.count()
2
shard1:SECONDARY> db.user.totalSize()
3694592
shard1:SECONDARY> db.user.totalIndexSize()
2695168
shard1:SECONDARY> db.user.stats()
{
        "ns" : "cndba.user",
        "size" : 68,
        "count" : 2,
        "avgObjSize" : 34,
        "storageSize" : 999424,
        "freeStorageSize" : 954368,
        "capped" : false,
……
        "nindexes" : 2,
        "indexBuilds" : [ ],
        "totalIndexSize" : 2695168,
        "totalSize" : 3694592,
        "indexSizes" : {
                "_id_" : 1544192,
                "_id_hashed" : 1150976
        },
        "scaleFactor" : 1,
……

进行压缩: 在副本集的从库执行时,可以不加force 选项:

shard1:SECONDARY> db.runCommand({compact:"user"})
{
        "bytesFreed" : 1114112,
        "ok" : 1,

shard1:SECONDARY> db.runCommand({compact:"user",force:true})

查看集合信息:

shard1:SECONDARY> db.user.count()
2
shard1:SECONDARY> db.user.totalSize()
1560576
shard1:SECONDARY> db.user.totalIndexSize()
978944
shard1:SECONDARY> db.user.stats()
{
        "ns" : "cndba.user",
        "size" : 68,
        "count" : 2,
        "avgObjSize" : 34,
        "storageSize" : 581632,
        "freeStorageSize" : 536576,
        "capped" : false,
……
        "nindexes" : 2,
        "indexBuilds" : [ ],
        "totalIndexSize" : 978944,
        "totalSize" : 1560576,
        "indexSizes" : {
                "_id_" : 942080,
                "_id_hashed" : 36864
        },
        "scaleFactor" : 1,
        "ok" : 1,
……

已经看到totalSize 和 totalIndexSize 都明显变小了。

查看节点状态:http://www.cndba.cn/cndba/dave/article/107985

shard1:SECONDARY> rs.status()
……
"stateStr" : "SECONDARY",
……

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
dave

dave

关注

人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业....."

  • 2279
    原创
  • 3
    翻译
  • 579
    转载
  • 196
    评论
  • 访问:8156772次
  • 积分:4413
  • 等级:核心会员
  • 排名:第1名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ