Shard Keys
在本页面
分片键确定集合documents在群集shards中的分布。分片键是存在于集合中每个文档中的索引field或索引compound字段。
使用分片键值范围的集合中的 MongoDB partitions数据。每个范围定义了分片键值的不重叠范围,并与chunk关联。
MongoDB 尝试在集群中的各个分片之间平均分配块。分片密钥与块分配的有效性直接相关。参见选择分片键。
Important
分片集合后,分片键和分片键值是不可变的。即
-
您不能为该集合选择其他分片键。
-
您无法更新分片键字段的值。
分片密钥规范
要分片集合,必须指定目标集合和sh.shardCollection()方法的分片键:
sh.shardCollection( namespace, key )
-
namespace
参数由字符串<database>.<collection>
组成,该字符串指定目标集合的完整namespace。 -
key
参数由一个包含字段和该字段的索引遍历方向的文档组成。
分片索引
所有分片集合 必须 具有支持shard key的索引;即索引可以是分片键上的索引,也可以是compound index,其中分片键是索引的prefix。
-
如果集合为空,则sh.shardCollection()在分片键上创建索引(如果该索引尚不存在)。
-
如果集合不为空,则必须先使用sh.shardCollection()创建索引。
Unique Indexes
您不能在hashed index上指定唯一约束。
对于远程分片集合,仅以下索引可以为unique:
-
分片键上的索引
-
compound index,其中分片键是prefix
-
默认的
_id
索引; 然而,_id
索引仅对每个分片强制执行唯一性约束 如果_id
字段不是分片键或分片键的前缀,则 。
Uniqueness and the _id Index
如果_id
字段不是分片密钥或分片密钥的前缀,则_id
索引仅对每个分片强制执行唯一性约束,而对每个分片则不强制执行约束。
例如,考虑一个跨越两个分片 A 和 B 的分片集合(具有分片键{x: 1}
)。由于_id
键不是分片键的一部分,因此该集合可能在分片 A 中具有一个_id
值1
的文档,而另一个文档具有分片 B 中的_id
值1
。
如果_id
字段不是分片密钥也不是分片密钥的前缀,则 MongoDB 期望应用程序在分片上强制_id
值的唯一性。
唯一的索引约束意味着:
-
对于要分片的集合,如果该集合具有其他唯一索引,则无法分片该集合。
-
对于已经分片的集合,不能在其他字段上创建唯一索引。
通过使用分片键上的唯一索引,MongoDB 可以对分片键值实施唯一性。 MongoDB 在* entire *键组合上强制唯一性,而不是分片键的单个组件强制唯一性。要对分片键值实施唯一性,请将unique
参数作为true
传递给sh.shardCollection()方法:
-
如果集合为空,则sh.shardCollection()在分片键上创建唯一索引(如果该索引尚不存在)。
-
如果集合不为空,则必须先使用sh.shardCollection()创建索引。
尽管您可以具有唯一的compound index,其中分片键是prefix,但是如果使用unique
参数,则集合必须在分片键上具有唯一索引。
选择分片键
分片键的选择会影响sharded cluster balancer如何在可用shards上创建和分配chunks。这会影响分片群集内操作的整体效率和性能。
分片密钥会影响分片群集使用的sharding strategy的性能和效率。
理想的分片密钥允许 MongoDB 在整个集群中平均分配文档。
至少要考虑cardinality,frequency和change潜在分片密钥的比率的后果。
Restrictions
有关分片键的限制,请参见分片键限制。
Collection Size
在分片不为空的集合时,分片键只能为初始分片操作限制最大支持的集合大小。参见Sharding Existing Collection Data Size
。
Important
成功分片后,分片集合可以增长到任何大小。
分片基数
分片键的cardinality确定平衡器可以创建的最大块数。这会降低或消除集群中水平缩放的有效性。
在任何给定时间,唯一的分片键值最多只能存在一个块上。如果分片密钥的基数为4
,则分片集群中最多只能有4
个块,每个块都存储一个唯一的分片密钥值。这也将集群中有效分片的数量也限制为4
-添加其他分片不会提供任何好处。
下图说明了使用字段X
作为分片键的分片群集。如果X
具有低基数,则插入的分布可能类似于以下内容:
在此示例中,群集不会*水平扩展,因为传入的写操作只会路由到分片的子集。
具有高基数的分片密钥虽然可以更好地促进水平扩展,但不能保证在分片集群中均匀分布数据。分片键的frequency和变化率也有助于数据分发。选择分片键时,请考虑每个因素。
分片频率
考虑一个代表分片键值范围的集合-分片键的frequency
代表给定值在数据中出现的频率。如果大多数文档仅包含这些值的子集,那么存储这些文档的块将成为群集中的瓶颈。此外,随着这些块的增长,它们可能会变成indivisible chunks,因为它们无法进一步拆分。这降低或消除了群集内水平缩放的有效性。
下图说明了使用字段X
作为分片键的分片群集。如果X
值的子集高频出现,则插入的分布可能类似于以下内容:
低频的分片密钥不能保证整个分片群集中的数据均匀分布。分片键的cardinality和变化率也有助于数据分发。选择分片键时,请考虑每个因素。
单调更改分片键
值单调增加或减少的分片键更有可能将插入内容分布到群集中的单个分片上。
发生这种情况是因为每个群集都有一个块,该块捕获上限为maxKey的范围。 maxKey
总是比所有其他值都高。类似地,有一个大块捕获了一个下限为minKey的范围。 minKey
总是比所有其他值都低。
如果分片键值始终在增加,则所有新插入都以maxKey
作为上限路由到块。如果分片键值始终在减小,则所有新插入都以minKey
作为下限路由到块。包含该块的分片成为写操作的瓶颈。
下图说明了使用字段X
作为分片键的分片群集。如果X
的值单调增加,则插入的分布可能类似于以下内容:
如果分片键值单调减小,则所有插入都将路由到Chunk A
。
不能单调更改的分片键不能保证在分片群集中均匀分布数据。分片键的cardinality和frequency也有助于数据分发。选择分片键时,请考虑每个因素。
如果您的数据模型需要对单调更改的键进行分片,请考虑使用Hashed Sharding。