MongoDB数据库在长期频繁地删除写入数据或批量删除了大量数据后,将产生很多物理空间碎片。这些碎片会占用磁盘空间,降低磁盘利用率。您可以对集合中的所有数据和索引进行重写和碎片整理,释放未使用的空间,提升磁盘利用率和查询性能。
背景信息
通常情况下,使用db.collection.remove({}, {multi: true})
命令删除文档,文档将从btree中删除,但是文档占用的物理空间不会被回收。如果执行remove
命令删除了大量的文档,且后续的数据写入操作很少,这将降低磁盘利用率,此时可执行compact
命令回收空闲的物理空间。
说明
- 当新写入的数据大小满足碎片空间大小时,该碎片空间就会被重复利用。所以在数据持续写入的场景中,不需要频繁执行
compact
命令整理物理空间碎片。
- 如您使用
db.collection.drop()
命令删除集合,那么集合的物理文件会被删除,且物理空间会被回收。
注意事项
- 执行该操作前,建议对数据库进行备份,备份方法请参见手动备份MongoDB数据。
- 执行该操作会导致集合所属的数据库被锁定,且该数据库的读写操作将被阻塞,建议您在业务低峰期操作。
说明 执行物理空间回收命令
compact
所需的时间与集合数据量、系统负载等因素有关。
预估回收的物理空间
- 通过MongoDB Shell连接MongoDB实例,不同类型实例的连接方法请参见:
- 执行如下命令,将数据库切换至集合所在的数据库。
use <database_name>
说明
- <database_name>:集合所在数据库名称。
- 您可以通过
show dbs
命令查询现有的数据库。
- 执行如下命令,查询对应集合物理空间的大小。
db.<collection_name>.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
说明
- <collection_name>:集合名。
- 您可以通过
show tables
命令查询现有的集合。
查询示例:
db.customer.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
执行结果示例:
207806464
整理单节点实例或副本集实例的碎片
- 通过MongoDB Shell连接MongoDB实例,不同类型实例的连接方法请参见:
- 切换至集合所在的数据库。
use <database_name>
说明 <database_name>:数据库名。您可以通过
show dbs
命令查询现有的数据库。
- 执行
db.stats()
命令查看碎片整理前数据库占用的磁盘空间。
- 执行以下命令,对某个集合进行碎片整理。
db.runCommand({compact:"<collection_name>",force:true})
说明
- <collection_name>:集合名。您可以通过
show tables
命令查询现有的集合。
force
为可选项,如您需要在副本集实例的Primary节点执行该命令,需要设置force
的值为true。
- 等待执行,返回
{ "ok" : 1 }
代表执行完成。
说明
- 如果您执行的目标是一个大集合,而
compact
命令马上就返回{ "ok" : 1 }
集合的物理空间也没有任何变化,则表示该集合没有必要进行碎片整理。
- compact操作不会传递给Secondary节点和Readonly节点,当实例为副本集实例并存在只读节点时,请重复上述步骤通过mongo shell连接至Secondary节点和Readonly节点,分别执行碎片整理命令。
碎片整理完毕后,可通过
db.stats()
命令查看碎片整理后数据库占用的磁盘空间。本案例碎片整理前后的对比如下图所示。
整理分片集群实例的碎片
说明 由于分片集群实例中只读节点当前不支持
compact
,所以当前无法使用
compact
整理只读节点的碎片。
- 通过mongo shell连接分片集群实例中的任一mongos节点,连接方法请参见mongo shell连接分片集群实例。
- 执行
db.stats()
命令查看碎片整理前数据库占用的磁盘空间。
- 执行以下命令,对Shard节点中的Primary节点进行集合的碎片整理。
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>",force:true}})
说明
- <Shard ID>:Shard节点ID。您可以登录MongoDB管理控制台,在目标实例的基本信息页面,查看Shard节点的ID。
- <collection_name>:集合名。您可以通过
show tables
命令查询现有的集合。
- 执行以下命令,对Shard节点中的Secondary节点进行集合的碎片整理。
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"},$queryOptions: {$readPreference: {mode: 'secondary'}}})
说明
- <Shard ID>:Shard节点ID。您可以登录MongoDB管理控制台,在目标实例的基本信息页面,查看Shard节点的ID。
- <collection_name>:集合名。您可以通过
show tables
命令查询现有的集合。