分片键确定集合文档在集群的分片中的分布。分片键是 集合中每个文档中存在的索引字段或索引复合字段。
MongoDB使用分片键值范围对集合中的数据进行分区。每个范围都定义了分片键值的非重叠范围,并与chunk关联。
MongoDB尝试在集群中的各个分片之间平均分配块。分片密钥与块分配的有效性直接相关。请参阅选择分片键。
重要
分片集合后,分片键的选择是不变的。即,您不能为该集合选择其他分片键。
从MongoDB 4.2开始,除非分片键字段是不可变_id
字段,否则您可以更新文档的分片键值。有关更新分片键的详细信息,请参阅“ 更改文档的分片键值”。
在MongoDB 4.2之前,文档的分片键字段值是不可变的。
要分片集合,必须指定目标集合和sh.shardCollection()
方法的分片键:
namespace
参数由一个字符串组成,该字符串
<database>.<collection>
指定目标集合的完整名称空间。key
参数包含一个文档,该文档包含一个字段和该字段的索引遍历方向。重要
分片集合后,分片键的选择是不变的。即,您不能为该集合选择其他分片键。
从MongoDB 4.2开始,除非分片键字段是不可变_id
字段,否则您可以更新文档的分片键值。有关更新分片键的详细信息,请参阅“ 更改文档的分片键值”。
在MongoDB 4.2之前,文档的分片键字段值是不可变的。
更新分片键值时
从MongoDB 4.2开始,除非分片键字段是不可变_id
字段,否则您可以更新文档的分片键值。要更新,请使用以下操作来更新文档的分片键值:
命令 | 方法 |
---|---|
update 与 multi: false |
|
findAndModify |
|
如果分片键修改导致将文档移至另一个分片,则在批量操作中不能指定多个分片键修改;即批量大小为1。 如果分片键修改不会导致将文档移动到另一个分片,则可以在批量操作中指定多个分片键修改。 |
所有分片集合必须有一个支持分片键的索引 ; 也就是说,索引可以是分片键的索引,也可以是 复合索引,其中分片键是索引的前缀。
sh.shardCollection()
则在分片键上创建索引(如果该索引尚不存在)。sh.shardCollection()
。如果删除了分片键的最后一个有效索引,请通过仅在分片键上重新创建索引来恢复。
您不能在哈希索引上指定唯一约束。
对于远程分片集合,只有以下索引可以是 唯一的:
分片键上的索引
默认_id
索引;不过,该_id
指数仅实施每碎片的唯一性约束,如果该_id
字段是不是分片键或片键的前缀。
唯一性与_id
索引
如果该_id
字段不是分片密钥或分片密钥的前缀,则_id
索引仅对每个分片强制执行唯一性约束,而不对每个分片实施唯一性约束。
例如,考虑一个跨越两个分片A和B的分片集合(具有分片键)。由于该键不是分片键的一部分,因此该集合中可能有一个文档的值在分片A中,而另一个文档的
值在分片B中。 。{x:
1}
_id
_id
1
_id
1
如果该_id
字段既不是分片密钥,也不是分片密钥的前缀,则MongoDB希望应用程序在_id
各个分片上强制值的唯一性。
唯一的索引约束意味着:
通过使用分片键上的唯一索引,MongoDB 可以
对分片键值实施唯一性。MongoDB在整个键组合上(而不是分片键的单个组件)实施唯一性。要对分片键值实施唯一性,请将unique
参数传递
true
给sh.shardCollection()
方法:
sh.shardCollection()
则在分片键上创建唯一索引(如果该索引尚不存在)。sh.shardCollection()
。尽管您可以拥有一个唯一的复合索引,其中分片键是一个前缀,但如果使用unique
parameter,则集合必须在分片键上具有一个唯一索引。
分片密钥的选择会影响可用分片上块的创建和分布。这会影响分片群集内操作的整体效率和性能。
理想的分片密钥允许MongoDB在整个集群中平均分配文档。
在分片不为空的集合时,分片键只能为初始分片操作限制最大支持的集合大小。请参阅
。Sharding Existing Collection Data Size
重要
成功进行分片后,分片集合可以增长到任何大小。
分片键的基数确定平衡器可以创建的最大块数。这会降低或消除集群中水平缩放的有效性。
在任何给定时间,唯一的分片键值最多只能存在一个块上。如果分片密钥的基数为4
,则分片4
集群中最多只能有多个块,每个块都存储一个唯一的分片密钥值。这也限制了集群中有效分片的数量4
-添加额外的分片不会提供任何好处。
下图说明了使用该字段X
作为分片键的分片群集
。如果X
基数较低,则插入的分布可能类似于以下内容:
在此示例中,群集无法水平扩展,因为传入的写入将仅路由到分片的子集。
具有高基数的分片密钥虽然可以更好地促进水平扩展,但不能保证在分片集群中均匀分布数据。分片密钥的频率和变化率也有助于数据分配。选择分片键时,请考虑每个因素。
如果您的数据模型需要在具有低基数的键上分片,请考虑使用具有较高相对基数的字段的复合索引。
考虑一个代表分片键值范围的集合-分片frequency
键的代表数据中给定值出现的频率。如果大多数文档仅包含这些值的子集,则存储这些文档的块将成为群集中的瓶颈。此外,随着这些块的增长,它们可能会变成不可分割的块,
因为它们无法进一步拆分。这降低或消除了群集内水平缩放的有效性。
下图说明了使用该字段X
作为分片键的分片群集。如果的值的子集X
出现频率很高,则插入的分布可能类似于以下内容:
低频的分片密钥不能保证整个分片群集中的数据均匀分布。分片密钥的基数和 变化率也有助于数据分配。选择分片键时,请考虑每个因素。
如果您的数据模型需要在具有高频值的键上分片,请考虑使用具有唯一或低频值的复合索引。
值单调增加或减少的分片键更有可能将插入内容分布到群集中的单个分片上。
发生这种情况是因为每个群集都有一个大块,该大块捕获具有maxKey上限的范围。maxKey
始终比较所有其他值。类似地,有一个块以minKey的下限捕获范围。
minKey
总是比所有其他值都低。
如果分片键值始终在增加,则所有新插入都maxKey
以上限为路由到块。如果分片键值始终在减小,则所有新插入都minKey
以下限为准路由到块。包含该块的分片成为写操作的瓶颈。
下图说明了使用该字段X
作为分片键的分片群集。如果的值X
单调增加,则插入的分布可能类似于以下内容:
如果分片键值单调递减,则所有插入都将路由到。Chunk A
不能单调更改的分片密钥不能保证在分片群集中均匀分布数据。分片密钥的 基数和 频率也有助于数据分配。选择分片键时,请考虑每个因素。
如果您的数据模型需要在单调变化的键上进行分片,请考虑使用Hashed Sharding。