列表字段可以是MongoDB中的分片键吗?

列表字段可以是MongoDB中的分片键吗?,mongodb,inner-join,sharding,Mongodb,Inner Join,Sharding,有些数据如下所示: widget: { categories: ['hair', 'nails', 'dress'] colors: ['red', 'white'] } SELECT * FROM widget_table WHERE categories == 'hair' AND colors == 'red' 需要按如下方式查询数据: widget: { categories: ['hair', 'nails', 'dress'] colors

有些数据如下所示:

widget:
{
    categories: ['hair', 'nails', 'dress']
    colors:     ['red', 'white']
}
SELECT * FROM widget_table WHERE categories == 'hair' AND colors == 'red'
需要按如下方式查询数据:

widget:
{
    categories: ['hair', 'nails', 'dress']
    colors:     ['red', 'white']
}
SELECT * FROM widget_table WHERE categories == 'hair' AND colors == 'red'
希望将此数据放入MongoDB分片集群。然而,理想的切分键似乎不是列表字段。在这种情况下,这是不可能的,因为所有字段都是列表字段

  • 是否可以使用列表字段,例如字段
    categories
    作为MongoDB中的分片键?
  • 如果是,我应该注意/注意哪些事情?
非常感谢

MongoDB中的切分(如2.4所述)通过基于属性将文档划分为不同的值范围来工作。列表或数组分片键作为分片键没有意义,因为它包含多个值

还值得注意的是,shard键是不可变的(一旦为文档设置,就不能更改),因此您不希望选择要更新的字段

如果文档中没有任何候选字段,则始终可以添加一个。在您的情况下,一个简单的解决方案是使用MongoDB 2.4中的新版本:

选择作为哈希切分键的字段应具有良好的基数,或具有大量不同的值。散列键适用于像ObjectId值或时间戳一样单调增加的字段


一个明显的问题是:“你需要碎片吗?”分片是使用MongoDB扩展写操作的一种方法,但如果您还没有达到当前配置的极限,则可能会有过大的杀伤力。

根据我得到的一些反馈,似乎断言不可能使用列表字段作为分片键进行分片,我想说明如何使用MongoDB的限制来分割这个用例:

原始对象: 数据层根据为切分键选择的字段中的元素数将对象拆分为多个指针对象: 说明:
  • 在MongoDB中,
    categories
    字段现在可以成为shard键
  • 原始对象现在将存储在键值存储中。对MongoDB中数据的查询将返回一个指针对象,该对象将用于从键值存储中获取该对象
  • 对MongoDB数据的查询将只命中一个碎片
  • 对MongoDB数据的插入将影响列表中元素的数量,在大多数情况下,只有一小部分碎片会受到影响

分片键不能是多键的,我不确定这是否会在使用MongoDB的数据集不可能分片后随时改变?可以分片,但不能在您列出的两个字段中的任何一个上,因此_id或更改您的模式。对我来说,这似乎是一个高度可疑的模式anyway@AsyaKamsky-这可以在列表字段之一上进行切分。该模式不适合分片。但是用例需要它。我意识到我提供的示例对象看起来很琐碎,但它被简化以删除不必要的细节。我们正在处理的数据在数千万个对象范围内,需要在使用我每分钟提供几千次的查询时进行查询。这就是为什么我说“或更改您的模式”-这就是您在回答中所做的。这使得您的问题“如何将模式更改为类别上的碎片”而不是“如何在数组字段上碎片”。我可能错了,但这似乎是错误的信息。使用GAE的大表,可以在非常大的范围内查询此类数据。为了做到这一点,数据必须跨多台机器进行分区。在我看来,如果您想使用“categories”作为切分键进行切分,那么数据库必须在索引中为“categories”列表中的每个值创建一行。如果列表中有4个元素,但有1000个碎片,则搜索的匹配项可以缩小到1000个碎片中的4个。添加哈希键不会提高指定查询的碎片的性能,因为查询必须检查所有碎片。@ChrisDutrow:您的问题特定于MongoDB,而不是BigTable?范围分区无疑是MongoDB分片的工作方式,您的分片键不能包含数组或列表。如果您的查询匹配四个碎片上的文档,则这是另一个问题。关于散列切分键:这里的建议只是因为您提到所有字段当前都是数组。MongoDB中的
\u id
字段不能是数组,因此仍然是候选字段。@ChrisDutrow:有关MongoDB中分片的介绍,请参阅:。TL;DR:如果你跳到幻灯片32(机制)的部分,你会发现一个分区方法的说明(逻辑块表示一系列文档碎片键)。这个答案不是“错误信息”-问是否可以做一些事情是相当奇怪的(MongoDB文档清楚地说不能)然后抱怨解释为什么不能这样做的答案是“错误的信息”,因为这不是你想要听到的。这是非常不相关的。您描述的是如何更改模式,以便可以在简单的categories字段上进行切分。不能将数组(列表)字段用作分片键。如果您更改模式,使其不再是数组,则可以对其进行切分。因为它不是一个列表。嗨,阿西娅。这个例子实际上展示了如何在MongoDB的限制下使用用例进行切分。数据层本身作为MongoDB之上添加功能的另一个数据库层。它使用MongoDB存储索引。最终的结果将是数据和索引在多台机器上分片。换句话说,读写操作只会影响机器的一个子集,向集群中添加更多的碎片或多或少会线性增加每单位时间内对数据执行的操作量。@ChrisDutrow:我同意