(1)对于那种持续增加的shard key,如日志中的时间字段,或者数据库中的自增字段;
采用这些字段做shard key会导致数据库的插入完全集中在最后一个分片上,导致写入压力比较大。
但是这种方式对数据库的查询有利。由于这种类型的应用,其访问的内容已经在内存当中,所以性能表现会不错。
一种解决方式是采用复合的shard key,如[timestamp, usename]
(2)随机分布的shard key
随机shard key在开始时没有问题,但是随着数据量的增大会导致数据库的性能下降。
一个是,为了平衡数据库的各个分片,mongodb须从磁盘读取相应的chunk,导致IO压力变大。
另外,这种访问的不规律,导致数据库频繁的从磁盘读入内存,开销较大。
如果我们的应用程序在很多时候都只访问近期的数据,我们会希望数据按照日期进行分布,但是考虑的性能问题,我们又希望数据均匀的分布在各个shard上。
为了解决这个问题,可以采用复合shard key
[coarselyAscending:1, search:1], coarselyAscending 一般是那种自增的字段,比如日期等,而search则是我们经常会进行查询的字段。
这样对于第一个字段coarselyAscending中每一个range中的数据,都会按照第二个字段均匀的分布在某几个shard上,从而想对应的提高数据库性能。
另外看过另外一篇博客的文章,印象比较深刻的准则有:
http://blog.youkuaiyun.com/zhangzhaokun/article/details/6324389
可靠性
选择分片Key的一个非常重要因素是万一某一个分片彻底不可访问了,受到影响的Chunk有多大(即使是用貌似可以信赖的Replica Set)。
假定,有一个类似于Twiter的系统,Comment记录类似如下形式:
{
_id: ObjectId("4d084f78a4c8707815a601d7"),
user_id : 42 ,
time : "2011-01-02T21:21:56.249Z" ,
comment : "I am happily using MongoDB",
}
由于这个系统对写操作非常敏感,所以需要将写操作扁平化的分布到所有的Server上去,这个时候就需要用id或者user_id来作为分片Key了。使用Id作为分片Key有最大粒度的扁平化,但是在一个分片宕机的情况下,会影响几乎所有的用户(一些数据丢失了)。如果使用User_id作为分片Key,只有极少比率的用户会收到影响(在存在5个分片的时候,20%的用户受影响),但是这些用户会再也不会看到他们的数据了。