限制:
在分片环境中,最大插入速率的限制是:
1.集群的分片数目
2.选择的片键
因为MongoDB使用基于片键范围的分块来分布数据,片键的选择可以控制MongoDB的数据分布,并影响系统写入和查询的性能。
理想状态下,片键应该具备以下两个特性:
1.在各个分片之间平衡数据插入。
2.大多数查询可以路由到满足需要的分片的子集。
但MongoDB很难满足下面这些标准:
时间戳
基于时间戳或者插入时间(也就是ObjectID)的片键最终都会变得越来越大,因此数据将插入单个分片。这会导致插入不平衡。
哈希(Hashs)
如果片键是随机的,那么查询将需要广播到所有的分片。该查询就不是可路由的。
下面将详细讨论如何选择分片和片键
选择1:根据时间分片
尽量使用时间戳,或者使用_id字段的ObjectID,会将数据平均分布在各个分片上,这将意味着分片集群拥有和单个实例相同的吞吐量。
假定频繁访问近期数据,那么大多数读操作倾向于读取集群中相同的分片。
选择2:根据半随机键来分片
为了将数据更平均的分布到分片上,可能需要考虑使用一个更随机的数据碎片,例如可以使用_id字段的hash值(也就是使用ObjectID作为片键)。
尽管这样会给应用程序需要生成片键,会带来一些额外的复杂性,但这么做会将写操作分布到多个分片上。例如如果有5个分片,就可以提供五倍于单个实例的写性能。
使用该片键,或者任何其他hash值来作为片键,有如下缺点:
1.片键和片键的索引将消耗数据库额外的存储空间。
2.查询(除非它们包含了片键本身)必须在所有分片上并行执行,这将导致性能的下降。
选择3:
如果文档里某个字段的值是在文档中平均分布的,那么强烈建议考虑使用该键作为片键。
例如可以考虑使用path字段,这样做的好处如下:
1.可以平均分布各个分片的写操作
2.读操作可以是有选择的,如果查询选择指定path字段,那么可以定位到单个分片上。
缺点如下:
所有命中一个特定的path的都必须指向同一个文件块(trunk),该块不能被MongoDB切分,因为该块中的所有文档都有相同的片键。如果网站有比较平均的负载,
这可能并不是一个问题。但是如果某一个页面有一个不成比例的访问,那么最终就会导致生成一个很大的文件块,该文件块不能被切分,并导致分片上的负载无法平衡。
选择4:综合使用固有的和合成的键来进行分片
MongoDB支持采用组合片键,该组合键可以综合选择2和选择3的最佳方面。在这些情形下,片键形式类似于{pash:1,ssd:1},这里path是一个经常使用的数据中固有的
键,而ssd一个_id字段的哈希值。
使用这种类型的片键,数据大体上根据固有的键来分布,也就是根据path来分布,这使得大多数查询只需要根据path字段访问单个或者一组分片。同时如果没有
足够多的path值用于分布,ssd使得MongoDB可以创建文件块来将数据分布到集群中多个分片上。
组合片键比较好的选择是一个有限范围的字段加一个无限范围的字段(递增或者随机)。