MongoDB 3.0最近被释放。而不是专注于新,很容易找到,而谈点,MongoDB初以来没有改变很多天。这个话题是分片和最特别的:如何选择一个好的分片键。注意,大多数的讨论也将适用于MySQL,所以如果你更感兴趣比MongoDB分片,仍然可能值得一读。
你什么时候想碎片吗?
一般建议分片MongoDB,一旦这些条件满足:
- # 1:一个服务器可以不再处理编写工作量。
- # 2:工作集不再适合在内存中。
- # 3:数据集太大很容易融入一个服务器。
请注意,# 1和# 2是目前最常见的原因为什么人们需要分片。还要注意,在MySQL世界,# 2并不意味着你需要分片。
一个好的分片键的性质是什么?
起点是一个跨切分查询分片环境中是非常昂贵的。很容易理解为什么:查询执行独立在几个碎片,然后合并结果。
MongoDB,蒙戈将透明地查询路由到正确的碎片,将自动合并结果:这是非常方便的,但隐藏的复杂性也可以让你忘记你执行一个非常劣质的查询。
这就是一个分片键的选择是至关重要:选择正确的关键和大多数查询将简单而高效,选择错了,你会有丑陋的和缓慢的查询。
实际上是一个很好的分片不需要的属性,但只有两个:
- 插入应该尽可能多的平衡在所有碎片。
- 每个查询的检索数据应该能够执行尽可能少的碎片(理想情况下1碎片)。
听起来很简单,对吗?但是根据你的用例,它可能很难找到一个好的分片键。让我们看看几个例子。
社交网络
说我们有用户谁可以连接到其他用户,谁能读或写的帖子,谁都有自己的墙。
3所有集合可以变得非常大,因此分片都将是必要的。
为用户和墙收集的user_id字段是一个显而易见的选择,它符合两个标准为一个好的分片键。
为帖子收集,user_id也看起来像一个显而易见的选择,但如果你认为如何读取访问集合,你会意识到你将需要使用它来获取它post_id,而不是它的user_id(因为一个用户可以有多个职位)。如果你碎片user_id,任何读到一个帖子将被广播给所有碎片:这显然不是一个很好的选择。
所以使用post_id是一个更好的选择。然而它只满足标准# 2:大多数从不更新帖子,所以所有的写操作都插入,会去一个碎片。然而交通收集强烈支持读取,所以能够加快读虽然不慢下来写可能是可以接受的折衷。
访问日志
这里的工作量是非常具体:写密集型和扩展。
切分的ObjectId绝对是一个坏主意:当数据可以很容易地跨越所有碎片,所有写只会去一个碎片,所以你将没有好处而non-sharded设置规模时写道。
更好的解决方案是使用一个散列的ObjectId:这样的数据和写将所有碎片。
另一个很好的选择是在文档中使用另一个领域,你知道是均匀地分布在整个数据集。这些领域可能不存在,这就是为什么散列ObjectId是一个更通用的解决方案。
电子商务
MongoDB可以是一个不错的选择来存储产品目录:无模式,它可以很容易地存储产品有不同的属性。
可用这种必须可搜索的目录。这意味着许多索引需要添加,和工作集可能会增长很快。在这种情况下你的主要问题可能不是规模写道,而是使读取尽可能高效。
分片可以是一个选择,因为如果操作得当,每个碎片将充当一个粗粒度的指数。现在的问题是要找到哪个字段(s)将均匀地分布数据集。最有可能的一个领域是不够的,你必须使用一个复合分片键。
在这里我想说,没有通用的解决方案,但如果产品例如针对孩子,女人或男人,如果你有几个类别的产品,一个潜在的分片键(目标、类别、sku)。
注意,在这种情况下,从辅助阅读可能足以确保良好的可伸缩性。
结论
正如你所看到的,选择一个正确的切分关键并不容易:不要认为因为一些应用程序由一些字段分片,你也应该这样做。你可能需要一个完全不同的策略或分片甚至可能不是正确的解决你的问题。
如果你有兴趣学习更多关于MongoDB,我将提供一个免费的研讨会3月25日上午10点。太平洋时间。它将介绍MongoDB MySQL dba和开发人员。注册在这里如果你是感兴趣的。





