为什么在 MongoDB 中对集合进行分片时我的数据目录如此之大?

Why are my data directories so large when sharding a collection in MongoDB?

我正在尝试对 MongoDB 中的集合进行分片,并创建了一些脚本来设置副本集,将它们添加到分片,然后将这些分片添加到我的主要 mongos 进程。

我用一个非常愚蠢的Python脚本生成数据:

import json

def gen_data(filename):
    with open(filename, 'w') as f:
        for i in range(100000*33):
            d = {"Hello": i, "World" : 99999-i}
            json.dump(d, f)
            f.write("\n")

if __name__ == "__main__":
    gen_data("my_data.json")

我创建了四个分片 (a, b, c, d),每个分片三个 repl 集 (0, 1, 2)。数据目录称为 a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2.

启用我的集合分片后,我将块大小设置为 100M,"hello.world"。我导入数据,在 '_id' 上建立索引,然后等待迁移。

我的平衡器完成 运行 后,我发现每个分片中的块数几乎相等,但块数对数据没有意义:

databases:
    {  "_id" : "hello",  "primary" : "a",  "partitioned" : true }
        hello.world
            shard key: { "_id" : 1 }
            unique: false
            balancing: true
            chunks:
                a   3
                b   3
                c   3
                d   2
//...

my_data.json 是 118M,但是当我检查我的数据目录的大小时,我很惊讶地发现它们每个都比原始数据大得多:

[erip@my_host shard_experiment]$ for s in {a..d}; do for n in {0..2}; do du -sh "$s$n"; done; done;
521M    a0
420M    a1
421M    a2
344M    b0
343M    b1
342M    b2
336M    c0
337M    c1
337M    c2
335M    d0
337M    d1
337M    d2

为什么我的数据目录这么大?我在设置分片服务器时使用 --smallfiles,但我发现导入如此小的文档的开销很大。

请注意,--smallfiles 选项仅适用于 MMAPv1 存储引擎,不适用于 MongoDB 3.2 中默认的 WiredTiger 存储引擎。

MongoDB Journal 很可能使用了相当数量的 space,每个节点大概 300MB。您可以通过 运行 验证这一点,例如:

find . -name "journal" -exec du -sh {} \;

此外,Replica Set Oplog 可能也使用了合理数量的 space。您可以通过登录副本集之一的 mongo shell 和 运行 db.printReplicationInfo() 来检查正在使用的 oplog 大小。您可以通过在首次启动副本集时设置 oplogSize 来减少这种情况。

像您这样拥有非常少量的数据,开销很大,但是随着您的数据变得越来越大,这种开销将只是很小的一部分。

块拆分是使用启发式算法预先完成的,因此您会看到拆分发生在块达到最大大小之前。