显然这是一个老问题,但我在研究 MongoDB 的时间序列数据时遇到了这个问题。我认为可能值得分享以下方法来提前分配完整的文档并执行更新操作,而不是新的插入操作。请注意,此方法已记录在案here http://www.mongodb.com/presentations/webinar-time-series-data-mongodb and here https://www.mongodb.com/blog/post/schema-design-for-time-series-data-in-mongodb.
想象一下您每分钟都在存储数据。考虑以下文档结构:
{
timestamp: ISODate("2013-10-10T23:06:37.000Z"),
type: ”spot_EURUSD”,
value: 1.2345
},
{
timestamp: ISODate("2013-10-10T23:06:38.000Z"),
type: ”spot_EURUSD”,
value: 1.2346
}
这与标准关系方法相当。在这种情况下,您将为每个记录的值生成一个文档,这会导致大量插入操作。我们可以做得更好。考虑以下:
{
timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"),
type: “spot_EURUSD”,
values: {
0: 1.2345,
…
37: 1.2346,
38: 1.2347,
…
59: 1.2343
}
}
现在,我们可以编写一份文档,并执行 59 次更新。这要好得多,因为更新是原子的,单个写入更小,并且还有其他性能和并发优势。但是,如果我们想在一个文档中存储一整天,而不仅仅是整个小时,该怎么办?这将需要我们遍历 1440 个条目才能获得最后一个值。为了改进这一点,我们可以进一步扩展到以下方面:
{
timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
type: “spot_EURUSD”,
values: {
0: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
1: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
…,
22: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
23: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343}
}
}
使用这种嵌套方法,我们现在最多只需步行 24 + 60 即可获得当天的最后一个值。
如果我们构建文档时,所有值都预先填充填充,我们可以确保文档不会改变大小,因此不会被移动。