我阅读了很多关于不同NoSQL数据库的内容,但我仍然不确定哪种解决方案在我的情况下最合适 - 可能是因为我没有使用NoSQL数据库的经验 - 除了REDIS,我用它来进行缓存。 / p>
在我的场景中,我必须为大约200,000个数据点存储基于时间的历史值(基于数据点的混合浮点数,整数,布尔值)。 通常每个数据点将每15分钟或更少获得一个新值,总计在每年<10亿个值的范围内。 某些数据点甚至可能每隔几秒存储一个值,单个数据点每年的理论最大值为31,536,000(我们不需要亚秒精度),但这种情况很少见。
未来数据点的数量可能会轻松翻倍,这意味着它必须是一个可扩展的系统。
为了使数据可视化,必须能够在任何存储的时间范围内快速分析单个数据点的数据 - 即几小时或一整年。在该范围内,我需要特定分辨率的最小/最大/平均值,通常是时间范围除以约1000。
在mySQL中可以这样做:
SELECT TRUNCATE(Timestamp / 3600) AS slot, MIN(value), AVG(value), MAX(value)
FROM data
WHERE Timestamp >= [from]
AND Timestamp < [to]
AND DatapointID = [some ID]
GROUP BY 1
...将返回图表的数据,精度为1小时。
如何使用NoSQL数据库完成这项工作,以便在几毫秒内获得信息?
这是我最关心的问题。
实时添加数据,因此不应该进行大量的写操作。必须能够更新现有数据,但这种情况极为罕见。数据将按时间排序,但我无法保证这一点。
哪种NoSQL数据库最适合这些需求,以及如何使用它完成上述数据查询?
答案 0 :(得分:1)
我想到的第一个问题是,为什么它必须是NoSQL数据库?您解释了如何在MySQL中执行此操作但未阅读为何您不想使用它。
首先,您建议对MySQl进行以下查询
SELECT TRUNCATE(Timestamp / 3600) AS slot, MIN(value), AVG(value), MAX(value)
FROM data
WHERE Timestamp >= [from]
AND Timestamp < [to]
AND DatapointID = [some ID]
GROUP BY 1
我建议使用以下查询;
SELECT TRUNCATE(Timestamp / 3600) AS slot, MIN(value), AVG(value), MAX(value)
FROM data
WHERE DatapointID = [some ID]
AND Timestamp >= [from]
AND Timestamp < [to]
GROUP BY 1
这是因为DatapointID应该是一个索引。所以MySQL可以限制id上的记录,然后查看Timestamp而不是搜索所有记录做一些数学然后匹配索引。
关于MySQL回答你关于NoSQL的问题。
去年我检查了CouchDB,MongoDB与MySQL的研究。虽然这是一个完全不同的用例,但我可以分享一些结果。
的MySQL
MongoDB的
CouchDB的
所以CouchDB的测试速度很慢。我只是插入简单的记录,不再有代码了。
MongoDB中的一个很好的功能是id还包含创建时间的时间戳。虽然当你想拥有数据时想要使用MongoDB是很棘手的。
MySQL查询也解释了,你需要索引来保持你的速度。 MongoDB支持它们。
希望信息有所帮助,这也有助于尝试一些数据库。通常只有一天玩数据库会给你更多的信息,然后一周阅读它们
第一次评论后在MongoDB中,SQL查询大致如下所示。
使用以下文档
因此,对于MongoDB,查询有两个部分,where子句和聚合。
在sql中where子句Timestamp >= [from] AND Timestamp < [to] AND DatapointID = [some ID]
MongoDB中的哪些地方很容易学习(我发现很容易)(有关详细信息,请参阅where docs&amp; find docs)。
但是那里的部分看起来像
{
DatapointID: ID,
Timestamp: {$gte: from},
Timestamp: {$lte: till},
}
ID
,from
&amp; till
是要填写的值!
然后硬部分进行聚合。但是,还有一些文档可以让事情变得更容易一些。请参阅aggregation docs&amp; match docs查看我从哪里获取信息。
但是群组功能看起来像以下
{
_id: 1,
minValues: {$min: value},
avgValue: {$avg: value},
maxValue: {$max: value},
}
_id: 1
是否有效,否则您需要有效的列 value
是记录中的列名。
现在我们需要完成查询。所以你可以执行它。它将在结尾处查看,如下所示:
db.articles.aggregate(
{ $match : {
DatapointID: ID,
Timestamp: {$gte: from},
Timestamp: {$lte: till},
} },
{ $group: {
_id: 1,
minValues: {$min: value},
avgValue: {$avg: value},
maxValue: {$max: value},
}}
);
代码未经过测试
答案 1 :(得分:1)
亨利克在答案中有很好的分数。
你的数字是合理的,恕我直言,但需要非常仔细的设计和选择工具。您没有描述有关f.ex的一些关键要求。在ACID领域,如果你甚至不需要“The D”,那么几乎任何可用的东西都是非常安全的。
考虑到你所说的话,我给出了一些评论:
也许你应该有一个“要求表”,以便能够决定走哪条路?相信我,NoSQL实施之间存在巨大的差异。
欢呼,// Jari