mongodb - 大量数据点的推荐树结构

时间:2014-10-21 22:28:42

标签: performance mongodb data-structures

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

由于我对mongodb来说相对较新,我很好奇可能是针对大量数据的推荐文档结构。情况如下:

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

就我将要解决的数据而言,我主要对两件事情感兴趣: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
 }

我只是不确定是否拥有包含3个索引的60亿个文档,或者拥有90,000个文档,每个文档包含67200个数组对象,并且使用聚合对性能会更好。

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

1 个答案:

答案 0 :(得分:2)

我会按照固定的时间间隔将文件结构化为特定地区的产品价格"。整个模式的时间间隔是固定的,但不同的模式由不同的选择产生,而应用程序的最佳模式可能需要通过测试来确定。选择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关于管理这样的时间序列数据。我基本上从那里解除了我的想法。