具有复合哈希分片密钥的MongoDB

时间:2020-10-14 11:44:02

标签: mongodb sharding

我试图了解在新的MongoDB(v 4.4)中分片的行为。

比方说,我的数据由可包含设备(多个组)的组(几个)组成。 所有这些设备将在一段时间(3-9个月)内存储一些与时间相关的值。

我最初的想法是为每24小时的数据创建一个设备文档(以避免达到16MB /文档的限制)。 这样,设备将类似于:

{
  _id: ObjectId(...)
  grp_id: ObjectId(...) // OR DBRef ?
  time_bucket: ISODate(...)
  data: {...} // data for the last 24 hours specified by time_bucket
}

现在进入分片键。 为了具有非单调性,我考虑使用{grp_id: "hashed"},因为这些将由用户分配,因此不会分配任何单调性。另外,smea组中的设备将位于同一碎片(在块限制内)。

但是组的基数和频率都很低,因此分片密钥应变为:{grp_id: "hashed", _id: 1}

但是,如果我随时间插入过多的设备数据,可能会造成麻烦,因此请再次优化密钥:{grp_id: "hashed", _id: 1, time_bucket: 1}。这也具有很好的本地化数据能力,它将在特定时间段内仅针对碎片。

现在要回答的问题:

  1. 这种方法在理论上会起作用吗?
  2. 如果我已经包含grp_id: "hashed",因为它是单调密钥,在密钥中包含_id: 1会产生负面影响吗?
  3. 如果我对_id而不是grp_id进行哈希处理,数据是否会在各个分片之间更均匀地分配(因为grp_id与设备相比具有很高的频率和低基数)?密钥将为{_id: "hashed", grp_id: 1, time_bucket: 1}。在这种情况下,grp_id会有助于数据的局部性,以便将来自同一组的设备放置在相同的分片上吗?

更笼统地说:我认为当使用散列键时,数据的分布方式有点困惑,而与基于范围的键结合使用另一个键,以及对于基于范围的键,您还可以定义区域的事实,我有点困惑(必须手动管理)。

我刚刚测试了两种分片方法,{grp_id: "hashed", _id: 1, time_bucket: 1}(初始)与{_id: "hashed", grp_id: 1, time_bucket: 1}(问题3):

第一种方法产生的碎片不平衡:

db.adminCommand({listDatabases:1, filter: {name: "test1"}})
{
        "databases" : [
                {
                        "name" : "test1",
                        "sizeOnDisk" : 22700032,
                        "empty" : false,
                        "shards" : {
                                "sharded-0" : 6377472,
                                "sharded-1" : 1425408,
                                "sharded-2" : 4210688,
                                "sharded-3" : 10686464
                        }
                }
        ],
        "totalSize" : 22700032,
        "totalSizeMb" : 21,
        "ok" : 1,
        "operationTime" : Timestamp(1602680982, 2),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1602680982, 2),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

第二个产生平衡的碎片:

db.adminCommand({listDatabases:1, filter: {name: "test2"}})
{
        "databases" : [
                {
                        "name" : "test2",
                        "sizeOnDisk" : 21512192,
                        "empty" : false,
                        "shards" : {
                                "sharded-0" : 5152768,
                                "sharded-1" : 5185536,
                                "sharded-2" : 5218304,
                                "sharded-3" : 5955584
                        }
                }
        ],
        "totalSize" : 21512192,
        "totalSizeMb" : 20,
        "ok" : 1,
        "operationTime" : Timestamp(1602682074, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1602682074, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

两个DB都包含6个组,每个组1000个设备,每个设备有30个实例(数据来自30天)。

我想知道背后的原因是什么,但我可能要问一个单独的问题。

0 个答案:

没有答案
相关问题