OPTIONS
翻译或纠错本页面

选择片键需要考虑的事情

选择一个片键

对许多集合来说,也许没有符合一个好的片键所需要的全部特征的单个自然存在的字段.以下的内容可以帮助在现有的数据中选择一个合适的片键.

  1. 在应用层计算一个合适的片键并存储在所有文档中.(xxxxx)

  2. 使用两个或者三个字段组成的复合索引做片键,以提供足够大的基数,写扩展和查询隔离.

  3. 通过以下过程确定如果选择的片键不是理想的,将不会在你的场景下造成问题:

    • 限制写的数量

    • 预计数据大小,或者

    • 应用的查询条件.

  4. 2.4 新版功能: 使用 hashed shard key .选择一个具有较大基数的字段,在这个字段上建立 散列索引,MongoDB使用这个散列索引做片键,以保证分片间数据的均衡.

    小技巧

    在进行查询时MongoDB会自动计算散列值,应用程序 不需要 计算散列值.

选择片键的注意事项.

选择片键的好坏很大程度上影响集群的性能,容量和功能.片键的选择应该考虑数据的结构,应用的查询与写入.

创建容易分割的片键

易于分割的片键使得MongoDB能够更容易地在分片间分配数据,如果片键的基数有闲,会造成数据块”不能被分裂”.

参见

基数能力

Create a Shard Key that has High Degree of Randomness

具有高随机性的片键可以避免一个分片承受绝大多数负载,并保证了分片间数据的均衡.

参见

写扩展

创建一个可以指向单个分片的片键

使用可以指向单个分片的片键, mongos 在进行大多数查询时只需要使用 特定的 mongod 即可,比如使用查询的主要的字段做片键.”随机性”很高的字段难以将请求发往特定的分片.

参见

查询隔离

使用复合索引做片键

进行片键选择时,明显的合适的片键可能并不存在.很多时候集合中任何一个字段都不是好的选择.这时候,通过计算确定一个特殊的字段,与已有的字段结合起来,或者用一个现有的字段结合起来做片键可能会更好一些.

基数能力

MongoDB中所说的基数能力,是指系统将数据 partition 分成 chunks 的能力.举例,假设有一个存储地址信息的 “address book” 集合.

  • 考虑使用 state(州) 字段作为片键:

    这个字段的取值范围是给定的一个列表,由于总的州的个数并不多,因此这个字段是 低基数 的,所有 state 相同的数据都必须存储在同一个数据块中,即使数据块大小已经超过配置的最大值.

    由于 state 字段的取值总数有限,MongoDB会把数据分布在有限的数据块中,并且很可能不均衡,这会带来一些影响:

    • 如果因为数据块中所有记录都拥有相同的片键,MongoDB不能对这个数据块进行分裂,那涉及到这个数据块的迁移就会花费很长时间,数据也很难保持均衡.

    • 如果你的数据块总数是固定的,那么集群中的分片数目不能超过数据块的总数.

  • 考虑使用 zipcode 字段做片键:

    虽然这个字段有很大的取值可能范围,即有很大的潜在的基数,但是依然有可能很多用户有相同的 zipcode , 这同样会使得数据块不能分裂.

    在这种情况下,基数能力取决于数据,如果你的地址簿存储的信息在地理上是分开的(比如”美国的干洗商家”),那邮编作为片键足够了.然而,如果你的地址簿存储的信息在地理上很接近,比如,在波士顿麻萨诸塞州的冰激凌店,那基数能力就较低.

  • 考虑使用 phone-number 字段做片键:

    电话号码是一个 高基数能力 的取值,因为每个人通常都有自己独一无二的电话号码,MongoDB可以按照需求分裂出很多数据块.

“高基数能力”对于集群中数据的均衡是必要的,但是这并不能保证实现 查询隔离 或者实现 写扩展.