问题描述
我试图了解在新的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}
。这也具有很好的本地化数据能力,它将在特定时间段内仅针对碎片。
现在要回答的问题:
- 这种方法在理论上会起作用吗?
- 如果我已经包含
grp_id: "hashed"
,因为它是单调密钥,在密钥中包含_id: 1
会产生负面影响吗? - 如果我对
_id
而不是grp_id
进行哈希处理,数据是否会在各个分片之间更均匀地分配(因为grp_id
与设备相比具有很高的频率和低基数)?密钥将为{_id: "hashed",grp_id: 1,time_bucket: 1}
。在这种情况下,grp_id
会有助于数据的局部性,以便将来自同一组的设备放置在相同的分片上吗?
更笼统地说:我认为当使用散列键时,数据的分布方式有点困惑,而与基于范围的键结合使用另一个键,以及对于基于范围的键,您还可以定义区域的事实,我有点困惑(必须手动管理)。
我刚刚测试了两种分片方法,{grp_id: "hashed",time_bucket: 1}
(初始)与{_id: "hashed",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,"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)
}
}
}
第二个产生平衡的碎片:
db.adminCommand({listDatabases:1,filter: {name: "test2"}})
{
"databases" : [
{
"name" : "test2","sizeOndisk" : 21512192,"shards" : {
"sharded-0" : 5152768,"sharded-1" : 5185536,"sharded-2" : 5218304,"sharded-3" : 5955584
}
}
],"totalSize" : 21512192,"totalSizeMb" : 20,"operationTime" : Timestamp(1602682074,1),"$clusterTime" : {
"clusterTime" : Timestamp(1602682074,"keyId" : NumberLong(0)
}
}
}
两个DB都包含6个组,每个组1000个设备,每个设备有30个实例(数据来自30天)。
我想知道背后的原因是什么,但我可能要问一个单独的问题。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)