【问题标题】:Mongodb data storage performance - one doc with items in array vs multiple docs per itemMongodb 数据存储性能 - 一个文档包含数组中的项目与每个项目多个文档
【发布时间】:2012-01-19 08:00:47
【问题描述】:

我在 Mongodb 集合中保存了每天为每条记录保存的统计数据。 例如,我的收藏看起来大致像

{ record_id: 12345, date: Date(2011,12,13), stat_value_1:12345, stat_value_2:98765 }

每个 record_id/date 组合都是唯一的。我使用 map-reduce 查询集合以获取给定日期范围内的每条记录的统计信息。

就读取查询性能而言,这种策略是否优于每个 record_id 存储一个包含统计数据数组的文档,就像上面的字典一样:

{ _id: record_id, stats: [
{ date: Date(2011,12,11), stat_value_1:39884, stat_value_2:98765 },
{ date: Date(2011,12,12), stat_value_1:38555, stat_value_2:4665 },
{ date: Date(2011,12,13), stat_value_1:12345, stat_value_2:265 },
]}

在专业方面,我需要一个查询来获取记录的整个统计历史记录,而无需使用较慢的 map-reduce 方法,另一方面,我必须总结给定日期范围内的统计数据在我的应用程序代码中,如果记录超出当前填充大小,则会进行一些磁盘重新分配。

【问题讨论】:

  • 每个记录 ID 的项目数是否有上限?
  • 没有上限,但实际上每条记录最多不会超过一两年的统计数据(最多 600-700 个统计数据)
  • 一些记录也会很少。 600-700 是上限(现实术语,未强制执行)

标签: mongodb


【解决方案1】:

我认为这取决于使用场景。如果单个聚合的数据集很小,例如 700 条记录,并且您希望实时执行此操作,我认为最好选择另一个选项并查询所有单个记录并在客户端聚合它们。这避免了 Map/Reduce 开销,更易于维护,并且不受重新分配或大小限制的影响。索引的使用应该是高效的和连接方面的,我怀疑有很大的不同:大多数驱动程序无论如何都是批量传输。

增加的灵活性可能会派上用场,例如,如果您想知道所有记录中某一天的统计值(如果这对您的应用程序有意义的话)。如果您需要存储更多 stat_values,则在子文档方法中,每条记录的最大日期数将下降。使用 db 文档而不是子文档通常也更容易。

如果您要跨多个服务器聚合大量数据,那么 Map/Reduce 真的很出色,否则带宽和客户端并发将成为瓶颈。

【讨论】:

  • 问题是,在一个请求中,我通常会获取大约 1000 条记录,每条记录都包含特定日期范围的聚合统计信息。在客户端上执行此操作是一个不错的选择,我将就客户端性能(它是一个 JavaScript 客户端)进行研究。
  • 嗯,我明白了。如果客户表现不佳且统计数据仅每天更改,那么保持较大的汇总(以一个月或一周为基础)如何?后台工作人员可以定期更新这些,客户端只需要聚合例如1 年文档、1 个月文档、2 周文档和 3 天文档,而不是 > 400 个文档
  • 是的,我们目前使用这样的缓存,但它只能在 4 小时内有效,因为统计信息每 4 小时更新一次。我们还缓存了自定义日期范围过滤器,这些过滤器最终会产生相当多的缓存数据。我用常规查询替换 map reduce 并在应用程序代码中进行总结的测试对于 1000 条记录集也很慢......我将测试每条记录 1 个文档的第二种方法,看看如何比较。似乎没有避免一个很好的旧 A/B 比较......
  • 是的,使用真实数据的真实测试是您唯一可以押注的性能:)
【解决方案2】:

我想你可以参考here,也可以看看foursquare如何解决这种问题here。它们都很有价值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多