我正在处理一个项目,该项目记录了多个地区的项目的价格历史记录,并且我计划将数据存储在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向导推荐吗?
答案 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关于管理这样的时间序列数据。我基本上从那里解除了我的想法。