我读了很多关于不同NoSQL数据库的文章,但我仍然没有决定哪种解决方案最适合我的情况——可能是因为我没有使用NoSQL数据库方面的经验——除了我用于缓存的REDIS。
在我的场景中,我必须为大约200000个数据点存储基于时间的历史值(基于数据点的混合浮点、整数、布尔值)通常每个数据点将每15分钟或更短时间获得一个新值,每年总计约为10亿个值一些数据点甚至可能每隔几秒钟存储一个值,单个数据点每年的理论最大值可达31536000个值(我们不需要亚秒精度),但这种情况很少见。
数据点的数量在未来可能很容易翻倍,这意味着它必须是一个可扩展的系统。
阅读
为了可视化数据,必须能够快速分析任何存储时间范围内单个数据点的数据,无论是几个小时还是一整年。在这个范围内,我需要特定分辨率的min/max/avg值,通常是时间范围除以大约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数据库做到这一点,以便在几毫秒内即可获得信息?
这是我最关心的问题。
写作
数据几乎是实时添加的,所以不应该有太多的写操作。更新现有数据必须是可能的,但极为罕见。数据会及时排序,但我不能保证。
其他必需品
- 必须能够将所有(或部分)数据快速复制到外部开发机器,这不需要数小时。这必须在不影响生产系统的情况下实现
- 必须能够在不停止数据库的情况下备份所有数据(每日备份)
- 我们必须导入大约5亿个现有数据,这些数据需要在合理的时间内完成
- 数据库必须可以用PHP访问
哪个NoSQL数据库最适合这些需求,如何使用它进行上述数据查询?
我想到的第一个问题是,为什么它必须是一个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上的记录,然后查看时间戳,而不是搜索所有记录。做一些计算,然后在索引上匹配。
关于MySQL,回到你关于NoSQL的问题。
去年,我查看了CouchDB、MongoDB和MySQL的研究。虽然这是一个完全不同的用例,我可以分享一些结果。
MySQL
- 读取:8.500条记录/秒
- 写入:400条记录/s
MongoDB
- 读取:17.500条记录/秒
- 写入:13.000条记录/s
沙发数据库
- read&写入:300条记录/s
所以CouchDB在我的测试中速度很慢。我只是插入简单的记录,不再有代码。
MongoDB中一个很好的特性是,id还包含创建它们的时间戳。尽管当您想要使用MongoDB时,当您已经有数据时,这是很棘手的。
MySQL查询也解释了这一点,您需要索引来保持高速。MongoDB支持它们。
- MongoDB有一个相当于mysqldump的东西,不知道它有多快,所以你必须用自己的数据来测试它
- 不确定这个
- 定义合理,但MongoDB的编写速度是MySQL的32.5倍
- 它有一个PHP驱动程序,所以有一个驱动程序
希望这些信息能有所帮助,也可以尝试一些数据库。通常一天只玩数据库会给你更多的信息,然后一周阅读
在第一条评论后编辑
在MongoDB中,SQL查询大致如下所示。
使用以下文档
- where文档
- 查找文档
- 聚合文档
- 匹配文档
因此,对于MongoDB,查询有两个部分,where子句和聚合。
在sql中where子句Timestamp >= [from] AND Timestamp < [to] AND DatapointID = [some ID]
MongoDB中的where实际上很容易学习(我发现它很容易)(请参阅where docs和find docs了解更多信息)。
但是哪里的部分看起来像
{
DatapointID: ID,
Timestamp: {$gte: from},
Timestamp: {$lte: till},
}
CCD_ 2、from
&till
是要填写的值!
然后,坚硬的部分构成了聚合。但是有一些医生可以让事情变得简单一点。所以请参阅聚合文档&匹配文档以查看我的信息来源。
但是组函数看起来像下面的
{
_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},
}}
);
未测试代码
Henriq的回答得分很高。
IMHO,你的数字是合理的,但需要非常仔细的设计和选择工具。你没有在ACID领域描述一些关于f.ex的关键要求,如果你甚至不需要"D",那么你几乎可以安全地使用任何可用的东西。
考虑到你所说的,我给出了一些评论:
- 您可以尝试一些创造性的方法,比如IMDB页面版本数据库,比如IBMSolidDB,而不是放弃现有的MySQL工作。它可以很好地扩展,备份也可以很容易地进行一些设计,因为您实际上可以在不破坏数据库的情况下将文件副本复制到其他系统(使用完整的ACID)
- 当然,我从No/NewSQL获得的经验仅限于我自己处理过的那些情况,但我所看到的都是对相同结论的支持:
- 卡桑德拉在专家手中是最可预测的。MongoDB"开箱即用"提供了一个很好的前景,但要扩大规模可能会很痛苦。Aerospike是一项功能强大的商业技术(具有alchemyDB背景)。VoltDB/HBase很有前景,但似乎存在一些可扩展性问题,我不确定它们的来源(调查不足)
也许你应该有一个"需求表"来决定该怎么走?相信我,NoSQL实现之间存在巨大的差异。
欢呼,//Jari