在MongoDB中使用巨大的“文档”是不是很好?

时间:2010-09-11 00:15:08

标签: ruby-on-rails mongodb mongoid

由于我们可以以任何方式构建MongoDB,我们可以这样做

{ products:
  [
    { date: "2010-09-08", data: { pageviews: 23, timeOnPage: 178 }},
    { date: "2010-09-09", data: { pageviews: 36, timeOnPage: 202 }}
  ],
  brands:
  [
    { date: "2010-09-08", data: { pageviews: 123, timeOnPage: 210 }},
    { date: "2010-09-09", data: { pageviews: 61, timeOnPage: 876 }}
  ]
}

因此,我们日复一日地向其添加数据,products文档和brands文档将变得越来越大。 3年后,productsbrands中将有一千个元素。对MongoDB不好吗?我们是否应该将其分解为4个文件:

{ type: 'products', date: "2010-09-08", data: { pageviews: 23, timeOnPage: 178 }}
{ type: 'products', date: "2010-09-09", data: { pageviews: 36, timeOnPage: 202 }}
{ type: 'brands', date: "2010-09-08", data: { pageviews: 123, timeOnPage: 210 }}
{ type: 'brands', date: "2010-09-08", data: { pageviews: 61, timeOnPage: 876 }}

那么3年后,将会有2000个“文件”?

5 个答案:

答案 0 :(得分:2)

假设你正在使用Mongoid(你标记它),你不会想要使用你的第一个架构想法。对于Mongoid来说,每次想要查找一个小值时,都会非常低效地提取这些巨大的文档。

对你来说可能是一个更好的模型是:

class Log
  include Mongoid::Document

  field :type
  field :date
  field :pageviews,    :type => Integer
  field :time_on_page, :type => Integer
end

这将为您提供如下文档:

{_id: ..., date: '2010-09-08', type: 'products', pageviews: 23, time_on_page: 178}

不要担心文件的数量 - Mongo可以处理数十亿个文件。您可以在类型和日期上编制索引,以便轻松找到您想要的任何数字。

此外,通过这种方式,通过驱动程序更新记录更加容易,甚至无需从数据库中提取记录。例如,在每个网页浏览中,您可以执行以下操作:

Log.collection.update({'type' => 'products', 'date' => '2010-09-08'}, {'$inc' => {'pageview' => 1}})

答案 1 :(得分:1)

我不是MongoDB专家,但1000不是“巨大的”。另外,我会严重怀疑包含4000个子元素的1个顶级文档和4个包含1000个子元素的顶级文档之间的差异 - 其中一个是六个一个与六个另一个问题。 / p>

现在,如果您正在讨论1个包含1,000,000个元素的文档而不是1000个文档,每个文档包含1000个元素,那么这是一个不同的数量级+,在存储时间或查询时间中,可能存在一个与另一个的优点。

答案 2 :(得分:0)

您已经讨论了如何更新数据,但您打算如何查询数据?它可能会对您应该如何构建文档产生影响。

在数组中使用嵌入式元素的问题是,每次添加时,它都可能不适合为文档分配的当前空间。这将导致(新)文档被重新分配和移动(该移动将需要重写文档的任何索引)。

我通常会建议您建议的第二种形式,但这取决于上述问题。

注意:4MB是任意限制,很快就会提升;您可以重新编译服务器以获得您想要的任何限制。

答案 3 :(得分:0)

您的设计似乎与关系表架构非常相似。

alt text

因此,添加的每个文档都是具有自己标识符的集合中的单独条目。虽然mongo文档大小限制为4 MB,但它足以容纳纯文本文档。而且您不必担心mongo中增长的文档数量,这就是基于文档的数据库的本质。

您唯一需要担心的是db集合的大小。 32位系统限制为2GB。因为MongoDB使用内存映射文件,因为它们与可用内存寻址相关联。这对64位系统来说不是问题。

希望这有帮助

答案 4 :(得分:0)

这又取决于您查询的用例。如果您真的关心单品,例如每天的产品:

{type:'products',date:“2010-09-08”,data:{pageviews:23,timeOnPage:178}}

然后您可以在一个日期中包含多天。

{type:'products',{date:“2010-09-08”,data:{pageviews:23,timeOnPage:178}}}

我们使用这样的东西:

{type:'products',“2010”:{“09”:{“08”:data:{pageviews:23,timeOnPage:178}}}}}

所以我们可以按天递增:{“$ inc”:{“2010.09.08.data.pageviews”:1}}

可能看起来很复杂,但优点是你可以在1条记录中存储关于“类型”的所有数据。因此,您可以检索单个记录并获取所有信息。