我需要存储来自不同位置的传感器数据(具有不同房间的不同工厂和每个不同的传感器)。数据定期从工厂现场设备下载,这些设备收集从所有传感器传输的数据。
传感器数据如下所示:
collecting_device_id, sensor_id, type, value, unit, timestamp
Type
可能是温度,unit
可能是degrees_celsius。 collecting_device_id
将识别工厂。
有很多不同的东西(==类型)被测量。
我将收集大约5亿到7.5亿行,然后对它们进行分析。
这是将数据存储在SQL数据库中的问题(假设在AWS RDS上使用MySQL InnoDB,必要时可以使用大型机器):
在考虑未来查询的查询性能时,最好将这些数据存储在一个巨大的表中,就像它来自传感器一样吗?或者将它分布在各个表格中(工厂的表格,温度,湿度,......,一切正常化)?或者为数据点设置一个包含不同字段的宽表?
是的,我知道,在不知道查询的情况下很难说“更好”。这里有更多信息和一些我想过的事情:
答案 0 :(得分:1)
不要预先优化。如果您不知道查询,那么您不知道查询。现在很容易做出选择,这将减慢一些查询子集。当您知道如何查询数据时,您可以优化 - 事后很容易规范化(例如将温度数据拉出到相关表中。)现在我建议您将它全部放在一个表中。
您可以考虑按日期对数据进行分区,或者您是否有其他可能有用的方法(记录设备可能?)。如果您有资源,通常会对此大小的数据进行分区。
答案 1 :(得分:1)
在考虑查询后,您可能会意识到您并不真正需要所有数据点。相反,例如,10分钟间隔的max / min / avg / etc可能就足够了。你可能想要"警告" on" over-temp"值。这不应该涉及数据库,但应该涉及接收传感器数据的程序。
所以,我建议不存储所有数据;而只存储汇总数据。这将大大缩小磁盘需求。 (如果您担心丢失原始文件,可以将原始数据存储到普通文件中。如果需要,可以很容易地重新处理原始文件。)
如果您决定将所有数据存储在表格中,那么我建议您使用以下提示:
每天750M行?每十年?每个月 - 没有太大的挑战。
通过每隔一天接收批次,将批量加载到临时表,进行规范化,汇总等变得非常容易;然后将结果存储在摘要表中,最后复制到'事实' table(如果您选择将原始数据保存在表中)。
在阅读我的提示时,您会注意到avg
未被汇总;而是sum
和count
。如果你需要标准偏差,也要保持平方和。
如果未能包含最终需要的所有摘要表,则重新处理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 NULL
(NULL
需要花费一些成本)等等。
当然,可以提出永不回复的查询。即使只有a
SELECT * FROM a JOIN a JOIN a JOIN a JOIN a
中的100行,这个也永远不会回来。结果集有100亿行。