06-选择片键
23.2.2 选择片键
对大型集合进行分片时,首先需要选择片键,这决定了如何在分片之间分配文档。片键为集合中每个文档都包含的索引字段或复合索引字段,MongoDB根据片键的值在集群的分片之间分配集合的文档。
为了让MongoDB提供所需的性能,选择合适的片键至关重要。糟糕的片键可能严重影响系统的性能,而好的片键可改善性能并确保未来的可扩展性。如果文档没有合适用作片键的字段,应考虑添加专门用作片键的字段。
选择片键时,别忘了考虑以下方面。
- 易于拆分: 片键应易于分割成块。
- 随机性: 使用基于范围的分片时,随机的片键可确保文档在分片之间的分配更平均,从而确保没有任何分片服务器负载过重。
- 复合键: 应尽可能使用单字段片键,但如何没有合适的单字段片键,可选择使用复合片键。相比于糟糕的单字段片键,这可提供更佳的性能。
- 基数: 基数(cardinality)指的是字段值的独一无二的程度。如果字段值是独一无二的(如社会保障号),字段的基数就很高;如果字段值独一无二的可能性较小(如眼睛颜色),字段的基数就很低。通常,基数较高的字段更适合用作片键。
- 以查询为导向: 研究您在程序使用中的查询。如果能够从单个分片收集到所有的数据,查询的性能将更佳。如果片键与常用的参数一致,将获得更佳的性能。例如,当所有查询都根据邮政编码查找用户时,可根据邮政编码对文档分片;这样,邮政编码相同的用户的文档都将位于同一个分片服务器中。如果查询使用的邮政编码相当分散,将邮政编码用作片键将是一个不错的主意;但如果大多数查询都只涉及几个邮政编码,将邮政编码用作片键就是馊主意,因为大多数查询都将发送给同一个服务器。
为说明片键,来看下面的例子。
- { "zipcode":1}:这个片键根据字段zipcode的值来分配文档。这意味着既有特定zipcode的查找都将发送给同一个分片服务器。
- { "zipcode":1, "city":1 }:这个片键首先根据字段zipcode的值来分配文档。如果有很多zipcode值相同的文档,它们可能根据字段city的值分配到不同的分片。这意味着不能保证基于相同邮政编码的查询都将发送给同一个分片服务器,但基于相同zipcode和city的查询将发送给同一个分片服务器。
- { "_id":"hashed" }:这个片键根据_id字段的散列值来分配文档,这确保文档在集群的分片服务器之间的分配更均匀,但无法保证查询只发送到单个片键服务器。