哈希分片
散列分片使用单个字段散列索引或复合散列索引(4.4 中的新增功能)作为分片键来跨分片集群对数据进行分区。
在单个字段散列索引上分片
哈希分片以减少Targeted Operations 与 Broadcast Operations为代价,在分片集群中提供更均匀的数据分布 。散列后,具有“关闭”分片键值的文档不太可能位于同一块或分片上 - 更有
mongos
可能执行 广播操作来完成给定的范围查询。mongos
可以将具有相等匹配的查询定位到单个分片。哈希索引计算单个字段的哈希值作为索引值;该值用作您的分片键。
在复合哈希索引上分片
MongoDB 4.4 添加了对使用单个 散列字段创建复合索引的支持。要创建复合散列索引,请在创建索引时指定
hashed
为任何单个索引键的值。复合哈希索引计算复合索引中单个字段的哈希值;该值与索引中的其他字段一起用作您的分片键。复合散列分片支持区域分片等功能,其中前缀(即第一个)非散列字段或字段支持区域范围,而散列字段支持分片数据的更均匀分布。复合哈希分片还支持带有哈希前缀的分片键,用于解决与单调递增字段相关的数据分布问题。
提示
MongoDB 在使用散列索引解析查询时自动计算散列。应用程序不需要计算哈希值。
警告
MongoDB
hashed
索引在散列之前将浮点数截断为 64 位整数。例如,hashed
索引将为包含值2.3
、2.2
和2.9
的字段存储相同的值。为防止冲突,请勿hashed
对无法可靠地转换为 64 位整数(然后再转换回浮点数)的浮点数使用索引。MongoDBhashed
索引不支持大于 2 53的浮点值。
从 4.0 版开始,mongosh
提供convertShardKeyToHashed()
方法。此方法使用与散列索引相同的散列函数,可用于查看某个键的散列值。
散列分片片键
您选择作为散列分片键的字段应该具有良好的 基数,或大量不同的值。散列键非常适合具有 单调更改字段(如ObjectId值或时间戳)的分片键。一个很好的例子是默认_id
字段,假设它只包含ObjectId值。
哈希与远程分片
给定一个使用单调递增值X
作为分片键的集合,使用范围分片会导致传入插入的分布类似于以下内容:
由于 的值X
始终在增加,因此上限为maxKey的块接收大多数传入写入。这将插入操作限制为包含此块的单个分片,从而减少或消除了分片集群中分布式写入的优势。
通过在 上使用散列索引X
,插入的分布类似于以下内容:
由于数据现在分布得更均匀,因此插入可以有效地分布在整个集群中。
分片集合
使用sh.shardCollection()
方法,指定集合的完整命名空间和目标散列索引以使用shard key 。
sh.shardCollection( "database.collection", { <field> : "hashed" } )
要在复合散列索引上分片集合 ,请指定集合的完整名称空间和目标复合散列索引以用作分片键:
sh.shardCollection(
"database.collection",
{ "fieldA" : 1, "fieldB" : 1, "fieldC" : "hashed" }
)
重要的
- 从 MongoDB 5.0 开始,您可以通过更改集合的分片键来重新分片集合。
- 从 MongoDB 4.4 开始,您可以通过向现有分片键添加一个或多个后缀字段来优化分片键。
- 在 MongoDB 4.2 及更早版本中,分片键的选择在分片后无法更改。
分片填充集合
如果您使用散列分片键分片填充的集合:
- 分片操作创建一个初始块以覆盖所有分片键值。
- 在初始块创建之后,平衡器在需要平衡数据时移动初始块的范围。
分片空集合
从 MongoDB 4.0.3 开始,如果已经为集合定义了区域和区域范围,则分片集合操作可以为空的或不存在的集合执行初始块创建和分发。块的初始创建和分发允许更快地设置分区分片。在初始分配之后,平衡器照常管理块分配。
在单字段散列分片键上分片空集合
- 没有为空的或不存在的集合指定区域和区域范围:
- 分片操作创建空块以覆盖分片键值的整个范围并执行初始块分配。默认情况下,该操作为每个分片创建 2 个块并跨集群迁移。您可以使用
numInitialChunks
选项指定不同数量的初始块。这种块的初始创建和分配允许更快地设置分片。 - 在初始分配之后,平衡器管理接下来的块分配。
- 分片操作创建空块以覆盖分片键值的整个范围并执行初始块分配。默认情况下,该操作为每个分片创建 2 个块并跨集群迁移。您可以使用
- 为空集合或不存在的集合指定区域和区域范围(从 MongoDB 4.0.3 开始可用):
- 分片操作为定义的区域范围创建空块以及任何其他块以覆盖分片键值的整个范围,并根据区域范围执行初始块分布。这种块的初始创建和分布允许更快地设置分区分片。
- 在初始分配之后,平衡器管理接下来的块分配。
使用散列字段前缀在复合散列分片键上分片空集合
如果复合散列分片键以散列字段作为前缀(即散列字段是分片键中的第一个字段):
- 没有为空的或不存在的集合指定区域和区域范围:
- 分片操作创建空块以覆盖分片键值的整个范围并执行初始块分配。所有非散列字段的值都
MinKey
在每个分割点。默认情况下,该操作为每个分片创建 2 个块并跨集群迁移。您可以使用numInitialChunks
选项指定不同数量的初始块。这种块的初始创建和分配允许更快地设置分片。 - 在初始分配之后,平衡器管理接下来的块分配。
- 分片操作创建空块以覆盖分片键值的整个范围并执行初始块分配。所有非散列字段的值都
- 单个区域的 范围从
MinKey
到MaxKey
指定为空或不存在的集合,presplitHashedZones
选项指定给sh.shardCollection()
:- 分片操作为定义的区域范围创建空块以及任何其他块以覆盖分片键值的整个范围,并根据区域范围执行初始块分布。这种块的初始创建和分布允许更快地设置分区分片。
- 在初始分配之后,平衡器管理接下来的块分配。
在具有非散列前缀的复合散列分片键上分片空集合
如果复合散列分片键有一个或多个非散列字段作为前缀(即散列字段不是分片键中的第一个字段):
由于没有为空或不存在的集合指定区域和区域范围,并且 preSplitHashedZones是
false
或被省略,MongoDB 在对集合进行分片时不执行任何初始块创建或分配。如果没有为空集合或不存在的集合指定区域和区域范围, 并且 preSplitHashedZones,
sh.shardCollection()
/shardCollection
会返回错误。为空或不存在的集合指定区域和区域范围,并将preSplitHashedZones选项 指定给
sh.shardCollection()
:- 分片操作为定义的区域范围创建空块以及任何其他块以覆盖分片键值的整个范围。
- 分片操作进一步细分每个范围的初始块,以便为区域中的每个分片分配相同数量的块。
- 这种块的初始创建和分布允许更快地设置分区分片。在初始分配之后,平衡器管理接下来的块分配。
每个区域的定义范围必须满足特定要求。有关要求的说明和完整示例,请参阅为空或不存在的集合预定义区域和区域范围。
原文链接:https://www.mongodb.com/docs/manual/core/hashed-sharding/
译者:陆文龙