选择分片键
分片键的选择会影响可用分片上数据块的创建和 分布 。数据的分布会影响分片集群内操作的效率和性能。
理想的分片键可以让 MongoDB 在整个集群中均匀地分发文档,同时也有利于实施常见的查询模式。
选择分片键时,请考虑:
注意
从 MongoDB 5.0 开始,您可以使用
reshardCollection
命令来更改分片键和重新分发数据。您可以使用
refineCollectionShardKey
命令来优化集合的分片密钥。refineCollectionShardKey
命令会向现有键添加一个或多个后缀字段以创建新的分片键。您可以更新文档的分片键值,除非分片键字段是不可变的
_id
字段。
重要
如果您定期更改文档的分片分片键值,以使该值位于不同分片拥有的分分片分片键范围,则可能会影响集群性能,因为在分片之间迁移文档会涉及额外的资源。 有关详细信息,请参阅使用数据段和数据库进行数据分区。 集合()。
分片键关联基数
分片键的关联基数决定了负载均衡器可以创建的最大数据段数。尽可能选择关联基数高的分片键。关联基数低的分片键会降低集群中水平扩展的有效性。
在任何给定时间,每个唯一的分片键值只能存在于一个数据段上。考虑一个数据集,它包含带有 continent
字段的用户数据。如果选择在 continent
上进行分片,则分片键的关联基数将为 7
。关联基数为 7
意味着分片集群内的数据段不能超过 7
个,每个数据段存储一个唯一的分片键值。这也会将集群中的有效分片数限制为 7
- 添加 7 个以上的分片不会带来任何好处。
下图展示了使用字段 X
作为分片键的分片集群。如果 X
的关联基数较低,则插入操作的分布情况可能如下所示:
如果数据模型要求在关联基数较低的键上进行分片,请考虑使用字段的复合索引来增加关联基数。
分片键频率
分片键的 frequency
表示给定分片键值在数据中出现的频率。如果多数文档仅包含可能的分片键值的一部分,则存储具有这些值的文档的数据段可能会成为集群内的瓶颈。此外,随着这些数据段的增长,它们可能会成为不可分割的数据段,因为它们无法被进一步分割。这会降低集群内横向扩展的有效性。
下图演示了使用字段 X
作为分片键的分片集群。如果 X
的子集值出现频率较高,则插入操作的分布情况可能如下所示:
如果数据模型要求在具有高频值的键上进行分片,请考虑使用唯一或低频率值的复合索引。
单调变化的分片键
针对单调增加或减少的值的分片键更有可能将插入操作分布到集群内的单个数据段中。
发生这种情况是因为每个集群都有一个捕获范围上限为maxKey的数据块。maxKey
始终是所有值中最高的值。 同样,有一个数据块捕获下限为minKey的范围。minKey
始终是所有值中最低的值。
如果分片键值总是增加,则所有新的插入操作都会路由到以 maxKey
为上限的数据段。如果分片键值总是减少,则所有新的插入操作都会路由到以 minKey
为下限的数据段。包含该数据段的分片会成为写入操作的瓶颈。
为优化数据分布,包含全局 maxKey
(或 minKey
)的数据段不会位于同一分片。分割数据段时,具有 maxKey
(或 minKey
)数据段的新数据段会位于不同的分片。
下图演示了使用字段 X
作为分片键的分片集群。如果 X
的值单调递增,则插入操作的分布情况可能如下所示:
如果分片键值单调递减,则所有插入操作都将改为路由到 Chunk A
。
如果您的数据模型需要对单调变化的键进行分片,可以考虑使用哈希分片。
分片查询模式
理想的分片键可将数据均匀地分布在分片集群中,同时也有利于实施常见的查询模式。选择分片键时,请考虑最常使用的查询模式以及给定分片键能否涵盖这些模式。
在分片集群中,如果查询包含分片键,则 mongos
仅会将这些查询路由到包含相关数据的分片。如果查询不包含分片键,则这些查询会被广播到所有分片以进行评估。这些类型的查询称为“分散-聚合”查询。每个请求涉及多个分片的查询效率较低,且向集群添加更多分片时无法实现线性扩展。
这不适用于针对大量数据进行操作的聚合查询。在这些情况下,“分散-聚合”查询可能是一种有用的方法,因为它允许查询在所有分片上并行运行。