一. 概述
分片键确定集合文档在集群分片中的分布。分片键可以是集合文档中的单索引或者是混合索引。
MongoDB 使用分片键值的范围在集合中分区数据。每个范围定义一个分片键值不重叠并且关联一个块。
MongoDB 尝试在集群中的分片上均匀地分布块。分片键直接关系到块分布的有效性。
重要:一旦对一个集合分片,分片键和分片值就不可改变。 如:不能给集合选择不同的分片键、不能更新分片键的值。
二. 分片键规范
对集合分片,你必须使用 sh.shardCollection() 方法指定集合和分片键。
sh
.
shardCollection
(
namespace
,
key
)
- namespace 参数是 database.collection,指定目标集合完整的命名空间
- 关键参数由包含字段和该字段的索引遍历方向的文档组成。
For instructions specific to sharding a collection using the
hashed sharding strategy, see
Shard a Collection using Hashed Sharding
For instructions specific to sharding a collection using the ranged sharding strategy, see Shard a Collection using Ranged Sharding.
三. 分片键索引
所有的分片集合必须有一个支撑 shard key 的索引。
- 如果集合为空,如果索引为空,则 sh.shardCollection() 在 shard key 上创建索引
- 如果集合不为空,你必须在使用 sh.shardCollection() 之前创建索引
如果删除分片键的最后一个有效索引,请通过仅在分片键上重新创建索引来恢复。
唯一索引
对于一个已分片的集合,只有 _id 字段索引和 shard key 上的单索引或者混合索引 是唯一的索引
- 你不能分片一个唯一索引在其他字段上的集合
- 你不能在一个已分片的集合上创建不同字段的唯一索引
通过使用shard key上的唯一索引,MongoDB可以强制shard键值的唯一性。 MongoDB对整个key组合,而不是分片密钥的单个组件实施唯一性。为了 shard 强制一致性,可以在 sh.shardCollection() 方法的 unique 参数传入 true 值:
- 如果集合为空,如果该集合的索引不存在则 sh.shardCollection() 在 shard key 上创建唯一索引
- 如果集合不为空,在使用 sh.shardCollection() 之前必须创建索引
四. 选择一个分片键
shard key 的选择影响着「分片集群均衡器」在可用分片上创建和分布 chunks。这影响着分片集群操作的整体效率和性能。
shard key 影响分片集群所使用的分片策略效率和性能
理想化的 shard key 可以让 documents 均匀地在集群中分布
限制
集合大小
当要分片的集合不为空的时候,shard key 可以限制集合的最大空间。
分片键基数
分片键基数决定着均衡器可以创建的最大 chunk 个数。这会减少或者移除集群水平扩展的效率。
一个唯一 shard key 任何时候只能在最多一个 chunk 中出现。如果 shard key 的基数是 4,那么集群中 chunks 的个数不能超过 4,各存储一个唯一 shard key 值。这将集群中有效分片的数量限制为4 - 添加其他分片不会提供任何好处。
下图显示了使用字段X作为分片键的分片集群。 如果X具有低基数,插入的分布可能看起来类似于以下:
在此示例中的集群不会水平扩展,因为传入写入只会路由到分片的子集。
具有高基数的 shard key 不能保证跨分片簇的数据的均匀分布,但是它更好地促进水平扩展。shard key 的频率和变化率也有助于数据分发。 选择分片键时请考虑每个因素。
如果您的数据模型需要对具有低基数的键进行分片,请考虑使用具有较高相对基数的字段来使用复合索引。
分片键频率(就是分片键的唯一性如何)
考虑一个表示分片键值范围的集合 - 分片键的频率表示给定值在数据中出现的频率。 如果大多数文档仅包含那些值的子集,则存储这些文档的块变为集群内的瓶颈。此外,随着这些块增长,它们可能变成不可分割的块,因为它们不能被进一步分裂。 这降低或消除了群集内水平扩展的有效性。
下图显示了使用字段X作为分片键的分片集群。 如果X的值的子集以高频出现,则插入的分布可以看起来类似于以下:
具有低频率的 shard key 不保证跨分片簇的数据的均匀分布。 shard key 的基数和变化率也有助于数据分发。 选择分片键时请考虑每个因素。
如果数据模型需要对具有高频率值的键进行分片,请考虑使用唯一或低频值使用复合索引。
单调改变的分片键
对单值增加或减少的值的分片键更可能将插入分发到集群中的单个分片。
这是因为每个集群都有一个捕获上限为maxKey的范围的块。 maxKey总是比所有其他值高。 类似地,存在捕获具有minKey的下限的范围的块。 minKey总是比低于所有其他值。
如果分片键值总是增加,则所有新插入都将路由到以maxKey作为上限的块。 如果分片键值总是递减,则所有新插入都将以minKey作为下限路由到块。 包含该块的分片成为写入操作的瓶颈。
下图显示了使用字段X作为分片键的分片集群。 如果X的值单调递增,插入的分布可能看起来类似于以下:
不单调改变的分片键不保证数据跨分片簇的均匀分布。 shard key 的基数和频率也有助于数据分发。 选择分片键时请考虑每个因素。
如果您的数据模型需要对单调变化的键进行分片,请考虑使用Hashed Sharding。
总结:
整篇其实就是为了说选择分片键要选择唯一性大的,随机性大的,推荐使用 Hash Sharding。
参考资料: