为什么DTS迁移数据前后的数据大小不一样

通过DTS迁移MongoDB数据后,您可能会发现目标实例与源实例上的数据量有所变化。本文将介绍排查数据量不一致的方法。

排查思路与方法

迁移完成后,如发现源实例和目标实例的数据量存在差异,您可以依次排查以下项:

  • 表内文档条数是否一致。

  • 索引个数以及大小是否一致。

  • WT引擎的可重用空间大小是否一致。

建议您通过mongo shell分别连接源实例和目标实例,执行以下命令确认数据量差异的原因:

  • 文档条数

    db.<collection>.stats().count
  • 索引

    db.<collection>.stats().indexSizes
  • 可重用空间

    db.<collection>.stats().wiredTiger["block-manager"]["file bytes available for reuse"]

测试结果

本文中迁移测试的环境说明如下。

项目

说明

地域及可用区

源实例和目标实例均位于华东1(杭州)地域可用区H。

实例版本及规格

源实例和目标实例版本及规格完全一致,具体参数如下:

  • 存储引擎:WiredTiger

  • 数据库版本:MongoDB 4.2

  • 规格:48 GB

  • 存储类型:SSD本地盘

  • 存储空间:500 GB

库表个数

4个表,分别为test1、test2、test3test4。

测试负载

采用YCSB压测工具进行压测。

表内文档条数

400万条。

文档总大小

10 KB左右,为10个纯二进制数据的字段。

迁移完成后源实例和目标实例的数据对比如下。

对比项

源实例

目标实例

差异(百分比)

count

(文档数)

4 * 4000000

4 * 4000000

0%

size

(逻辑存储大小)

4 * 4671518072

4 * 4671518072

0%

storageSize

(物理存储大小)

test1:10284060672

test2:9059483648

test3:8771850240

test4:9562763264

test1:4786364416

test2:4786380800

test3:4801978368

test4:4786257920

test1:5.1GB(53%)

test2:3.9GB(47%)

test3:3.7GB(45%)

test5:4.4GB(50%)

indexSize

(索引大小)

test1:{ "_id_" : 197046272 }

test2:{ "_id_" : 210997248 }

test3:{ "_id_" : 211079168 }

test4:{ "_id_" : 201854976 }

test1:{ "_id_" : 97783808 }

test2:{ "_id_" : 97742848 }

test3:{ "_id_" : 102924288 }

test4:{ "_id_" : 97742848 }

test1:0.09GB(50%)

test2:0.11GB(53%)

test3:0.1GB(51%)

test4:0.1GB(52%)

reuse size

(重用空间大小)

test1: 4987596800

test2: 3646660608

test3: 3984535552

test4: 4774940672

test1:237568

test2:237568

test3:176128

test4:237568

不涉及

storage-reuse

(物理存储大小-重用空间大小)

test1: 5296463872

test2: 5412823040

test3: 4787314688

test4: 4787822592

test1:4786126848

test2:4786143232

test3:4801802240

test4:4786020352

test1:0.47GB(9.6%)

test2:0.58GB(11.6%)

test3:-13.4MB(-0.3%)

test4:1.7MB(<0.1%)

通过上表可以得出以下结论:

  • 源实例与目标实例的文档数和逻辑存储大小一致,表示DTS已经成功将数据从源端迁移到目标端。

  • 源实例的存储和索引占用的空间更大,这种情况是因为源实例在DTS迁移前执行过一批UPDATE操作。

  • 相同文档数以及逻辑大小的合集,实际的物理大小也会有细微差异。

  • 排除索引大小以及重用空间大小后,源实例和目标实例的存储空间依然可能有10%左右的差异。

数据的写入方式不同,可能会导致两个相同文档条数的实例的存储大小不同,因为WiredTiger页面的存储和拆分方式可能不同,索引的生成方式有所差异,为了对齐而填充(padding)的内碎片以及数据块的压缩率也会有所差异。因此,源实例和目标实例存储空间大小差异在10%以内都属于符合预期的情况。

补充说明:DTS的实现原理

不同于云数据库MongoDB的物理备份和快照备份,DTS为了兼容更多版本以及不同架构,使用了逻辑同步的方式。所有的文档数据都会被重新插入一遍,因此索引也会重新生成。

DTS迁移数据分为全量迁移和增量迁移两个步骤,这两个步骤均属于逻辑同步,类似于mongodumpmongorestore。全量迁移和增量迁移的迁移流程如下:

  • 全量迁移:DTS会扫描源端每个表的全部记录,然后批量插入到目标端,理论上每个表单线程并发迁移,如果单表的内容非常多,DTS会把大表按_id分段拆分,然后每个范围一个线程迁移,总线程数会控制一个上限。

  • 增量迁移:DTS会直接拉取源端的oplog,然后在目标端回放。

更多关于DTS的介绍,请参见什么是数据传输服务DTS