在SQL中存储大量传感器数据,优化查询性能

时间:2016-11-25 16:33:13

标签: mysql sql performance sensor bigdata

我需要存储来自不同位置的传感器数据(具有不同房间的不同工厂和每个不同的传感器)。数据定期从工厂现场设备下载,这些设备收集从所有传感器传输的数据。

传感器数据如下所示:

collecting_device_id, sensor_id, type, value, unit, timestamp

Type可能是温度,unit可能是degrees_celsius。 collecting_device_id将识别工厂。

有很多不同的东西(==类型)被测量。

我将收集大约5亿到7.5亿行,然后对它们进行分析。

这是将数据存储在SQL数据库中的问题(假设在AWS RDS上使用MySQL InnoDB,必要时可以使用大型机器):

在考虑未来查询的查询性能时,最好将这些数据存储在一个巨大的表中,就像它来自传感器一样吗?或者将它分布在各个表格中(工厂的表格,温度,湿度,......,一切正常化)?或者为数据点设置一个包含不同字段的宽表?

是的,我知道,在不知道查询的情况下很难说“更好”。这里有更多信息和一些我想过的事情:

  • 没有恒定的数据流,因为数据每2天以块的形式上传(上传时大量写入,其余时间根本没有写入),所以我猜测索引维护不会是一个大问题
  • 我会尝试减少预先插入的数据量(以后可以轻松复制的数据,不添加其他信息的数据,......)
  • 尚未定义应执行的查询(我知道,设计查询会在性能方面产生很大差异)。这是探索性的工作(因此我们不知道将要求什么,并且不能轻易地预先计算值),所以有一次你想要将一个时间范围内的数据点与另一个类型的数据点进行比较,另一次你可能想要比较工厂的房间,计算相关性,找到重复的等等。
  • 如果我有多个表并规范化所有查询需要很多连接(可能会使一切都很慢)
  • 查询主要需要在整个~5亿行数据库上执行,很少在单独下载的子集上执行
  • 用户很少(< 10),其中大部分都会执行这些“复杂”查询。
  • SQL数据库是一个不错的选择吗?对于使用NoSQL系统的这个用例,性能方面会有很大差异吗?
  • 在这个包含大量数据的设置中,我是否会有从不“回来”的查询? (考虑到查询不是太愚蠢: - ))。

2 个答案:

答案 0 :(得分:1)

不要预先优化。如果您不知道查询,那么您不知道查询。现在很容易做出选择,这将减慢一些查询子集。当您知道如何查询数据时,您可以优化 - 事后很容易规范化(例如将温度数据拉出到相关表中。)现在我建议您将它全部放在一个表中。

您可以考虑按日期对数据进行分区,或者您是否有其他可能有用的方法(记录设备可能?)。如果您有资源,通常会对此大小的数据进行分区。

答案 1 :(得分:1)

在考虑查询后,您可能会意识到您并不真正需要所有数据点。相反,例如,10分钟间隔的max / min / avg / etc可能就足够了。你可能想要"警告" on" over-temp"值。这不应该涉及数据库,但应该涉及接收传感器数据的程序。

所以,我建议存储所有数据;而只存储汇总数据。这将大大缩小磁盘需求。 (如果您担心丢失原始文件,可以将原始数据存储到普通文件中。如果需要,可以很容易地重新处理原始文件。)

如果您决定将所有数据存储在表格中,那么我建议您使用以下提示:

每天750M行?每十年?每个月 - 没有太大的挑战。

通过每隔一天接收批次,将批量加载到临时表,进行规范化,汇总等变得非常容易;然后将结果存储在摘要表中,最后复制到'事实' table(如果您选择将原始数据保存在表中)。

在阅读我的提示时,您会注意到avg未被汇总;而是sumcount。如果你需要标准偏差,也要保持平方和。

如果未能包含最终需要的所有摘要表,则重新处理Fact表(或Fact文件)以填充新的摘要表并不困难。这是一次性任务。之后,每个块的汇总应该使表保持最新。

事实表应该标准化(用于空间);摘要表应该有些非规范化(性能)。究竟有多少非规范化取决于大小,速度等,并且无法在此级别的讨论中进行预测。

"查询500M行" - 设计摘要表,以便可以针对它们完成所有查询。一个起始的经验法则:任何Summary表的行数应该是Fact表的十分之一。

索引...... Fact表应该只有一个主键。 (前100M行可以很好地工作;最后100M行运行得很慢。这是你不想学习项目11个月的课程;所以要预先优化。)汇总表应该有无论哪种指数都有意义这也使得查询Summary表的速度比Fact表更快。 (注意:在500M行表上设置二级索引本身就是一个非常重要的性能问题。)

NoSQL会强制您重新发明SQL,或者依赖于强力全表扫描。摘要表是真正的解决方案。在一个(虽然极端)的情况下,我通过使用Summary表将1小时的查询加速到2秒。所以,我投票支持SQL,而不是NoSQL。

至于是否预先优化" - 我说它比重建一个500M行表要容易得多。这带来了另一个问题:开始每个字段的最小数据大小:查看MEDIUMINT(3个字节),UNSIGNED(一个额外的位),CHARACTER SET ascii (utf8或utf8mb4)仅适用于需要它的列),NOT NULLNULL需要花费一些成本)等等。

当然,可以提出永不回复的查询。即使只有a SELECT * FROM a JOIN a JOIN a JOIN a JOIN a中的100行,这个也永远不会回来。结果集有100亿行。