【问题标题】:mongodb - Recommended tree structure for large amount of data pointsmongodb - 大量数据点的推荐树结构
【发布时间】:2014-10-21 22:28:42
【问题描述】:

我正在开展一个项目,该项目记录跨多个地区的商品价格历史记录,并且我计划将数据存储在 mongodb 集合中。

由于我对 mongodb 比较陌生,我很好奇对于大量数据可能推荐的文档结构。情况如下:

我正在记录大约 200 个地区的大约 90,000 件商品的价格历史记录。我希望每小时记录每件商品的价格,并为任何给定商品提供 2 周的历史记录。这大约是 (90000*200*24*14) ~= 60 亿个数据点,或者每个项目大约 67200 个。每天将运行一次清理查询以删除超过 14 天的记录(更具体地说,将其归档到 gzip 压缩的 json/文本文件)。

就我将要从中获得的数据而言,我主要对两件事感兴趣:1) 特定地区的特定商品的价格历史记录,以及 2) 特定商品的价格历史记录所有地区。

在我真正开始导入这些数据并运行基准测试之前,我希望有人能够就我应该如何构建它以允许通过查询快速访问数据提供一些建议。

我正在考虑以下结构:

{
    _id: 1234,
    data: [
        {
            territory: "A",
            price: 5678,
            time: 123456789
        },
        {
            territory: "B",
            price: 9876
            time: 123456789
        }
    ]
}

每个项目都是它自己的文档,每个地区/价格点为该项目在特定地区。我遇到的问题是检索特定商品的价格历史记录。我相信我可以通过以下查询完成此操作:

db.collection.aggregate(
    {$unwind: "$data"},
    {$match: {_id: 1234, "data.territory": "B"}}

)

我正在考虑的另一种选择是将每个数据点放在自己的文档中,并在项目和区域上放置一个索引。

// Document 1
{
    item: 1234,
    territory: "A",
    price: 5679,
    time: 123456789
}
// Document 2
{
    item: 1234,
    territory: "B",
    price: 9676,
    time: 123456789
 }

我只是不确定拥有 60 亿个文档和 3 个索引,还是拥有 90,000 个文档和 67200 个数组对象并使用聚合来提高性能。

或者也许还有一些其他的树结构或处理这个问题的好人和 MongoDB 向导可以推荐?

【问题讨论】:

  • 这有点主观,确实应该回答,但要问自己“将项目保存在数组中有什么好处?”。 MongoDB 中数组的总体思路是将相关数据保存在以这种方式访问​​的地方。这意味着如果您使用单个文档并一起读/写所有或多个数组点,则使用数组。如果不是,那么数组不是最佳选择。销售订单和项目是一个不错的选择,但其他东西可能不是。

标签: performance mongodb data-structures


【解决方案1】:

我会将文档构建为“在给定区域内每个固定时间间隔内的产品价格”。整个模式的时间间隔是固定的,但不同的模式来自不同的选择,最适合您的应用程序的模式可能需要通过测试来确定。选择时间间隔为 1 小时给出了您的第二个架构想法,总共有大约 60 亿个文档。您可以选择时间间隔为 2 周(不要)。在我看来,选择的最佳时间间隔是 1 天,所以文档看起来像这样

{
    "_id" : ObjectId(...), // could also use a combination of prod_id, terr_id, and time so you get a free unique index to look up by those 3 values
    "prod_id" : "DEADBEEF",
    "terr_id" : "FEEDBEAD",
    "time" : ISODate("2014-10-22T00:00:00.000Z"), // start of the day this document contains the data for
    "data" : [
        {
            "price" : 1234321,
            "time" : ISODate("2014-10-22T15:00:00.000Z") // start of the hour this data point is for
        },
        ...
    ]
}

我喜欢 1 天的时间间隔,因为它在文档数量(主要与索引大小相关)、文档大小(16MB 限制,必须通过网络传输)和淘汰旧文档的便利性之间达到了很好的平衡(保持 15 天,每天从第 15 天开始擦除+存档)。如果您在{ "prod_id" : 1, "terr_id" : }` 上放置一个索引,那应该可以让您有效地完成您的两个主要查询。您可以通过预先分配每天的文档来获得额外的性能提升,以便及时更新。

根据构建 MMS 监控系统的经验,有一个 great blog post 关于管理这样的时间序列数据。我基本上已经从那里提升了我的想法。

【讨论】:

    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 2010-11-14
    • 2016-03-04
    • 1970-01-01
    • 2013-06-27
    • 2012-07-02
    相关资源
    最近更新 更多