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

Posted

技术标签:

【中文标题】在 SQL 中存储大量传感器数据,优化查询性能【英文标题】:Store large amounts of sensor data in SQL, optimize for query performance 【发布时间】:2016-11-25 16:33:12 【问题描述】:

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

传感器数据如下所示:

collecting_device_id, sensor_id, type, value, unit, timestamp

Type 可以是温度,unit 可以是摄氏度。 collecting_device_id 将识别工厂。

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

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

这是一个问题,用于将数据存储在 SQL 数据库中(假设是 AWS RDS 上的 mysql InnoDB,如果需要,可以使用大型机器):

在考虑未来查询的查询性能时,将这些数据存储在一个巨大的表中是否更好,就像它来自传感器一样?或者将其分布在表格中(工厂表格、温度、湿度……,一切都标准化了)?或者有一个包含不同字段的宽表?

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

没有恒定的数据流,因为数据每 2 天以块的形式上传(上传时写入很多,其余时间根本没有写入),所以我猜索引维护不会是一个大问题. 我将尝试减少预先插入的数据量(以后可以轻松复制的数据、不添加额外信息的数据……) 尚未定义应该执行的查询(我知道,设计查询在性能方面有很大的不同)。这是探索性的工作(所以我们不知道会被问什么,也不能轻易地预先计算值),所以有一次你想将一个时间范围内的一种类型的数据点与另一种类型的数据点进行比较,另一次您可能想要比较工厂中的房间、计算相关性、查找重复项等。 如果我有多个表并对所有内容进行规范化,则查询将需要大量连接(这可能会使一切变得非常缓慢) 查询大多需要在整个 ~ 5 亿行数据库上执行,很少在单独下载的子集上执行 用户将很少 ( SQL 数据库是一个好的选择吗?这个用例使用 NoSQL 系统在性能方面会有很大差异吗? 在这个数据量如此之大的设置中,我是否会有永远不会“返回”的查询? (考虑到查询不是太愚蠢:-))

【问题讨论】:

具有适当索引的垂直缩放 SQL 数据库应该能够处理此问题。我听说亚马逊有这种大小的关系数据库。从存储的角度来看,NoSQL 可能更便宜,但对于复杂的查询,完全忘记返回的查询。 【参考方案1】:

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

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

【讨论】:

通常我也会说“不要预优化”。然而,对于如此规模的项目,很多教训是没有吸取到的,直到“为时已晚”来修复它们。我在我的答案中介绍了一些课程。 @RickJames -- 你的答案的第一行提到了知道查询是什么的要求 -- 这个问题的重点(在我看来)是提问者 不知道查询是什么,想知道如何优化。除了那个“小”问题,你的答案非常好。 啊,是的。有时,我建议将原始传入数据存储在一个平面文件中以防万一您以后决定需要一些东西。通常这样的文件比 db 中的等效 Fact 表要小得多。如果需要,必须编写一个特殊的程序来重新读取数据。【参考方案2】:

在您考虑查询之后,您可能会意识到您并不真正需要所有数据点。相反,例如 10 分钟间隔的 max/min/avg/etc 可能就足够了。而且您可能希望对“过温”值进行“警报”。这不应该涉及数据库,而应该涉及接收传感器数据的程序。

所以,我建议不要存储所有数据;而是只存储汇总数据。这将大大缩小磁盘需求。 (您可以将“原始”数据存储到纯文件中,以防您担心丢失它。如果需要,重新处理原始文件将非常容易。)

如果您决定将所有数据存储在表中,那么我推荐以下提示:

High speed ingestion(包括规范化技巧) Summary Tables Data Warehousing Time series partitioning(如果您打算删除“旧”数据)(以后添加分区很痛苦)

7.5 亿行——每天?每十年?每月 - 没有太多挑战。

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

在阅读我的提示时,您会注意到avg 没有总结;而sumcount 是。如果您需要标准差,也请保留平方和。

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

事实表应该被规范化(用于空格);汇总表应该有些非规范化(为了性能)。究竟有多少非规范化取决于大小、速度等,在这个讨论级别无法预测。

“查询 500M 行”——设计汇总表,以便可以对它们进行所有查询。一个起始的经验法则:任何摘要表的行数都应该是事实表的十分之一。

索引... Fact 表应该只有一个主键。 (前 100M 行会很好地工作;最后 100M 行运行速度会很慢。这是一个你不想在项目 11 个月内学习的课程;所以做预优化。)摘要表应该有任何索引有道理。这也使得查询汇总表比查询事实表更快。 (注意:在 500M 行的表上拥有二级索引本身就是一个重要的性能问题。)

NoSQL 要么迫使您重新发明 SQL,要么依赖于暴力全表扫描。汇总表是真正的解决方案。在一个(尽管是极端的)情况下,我通过使用汇总表将 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 亿行。

【讨论】:

以上是关于在 SQL 中存储大量传感器数据,优化查询性能的主要内容,如果未能解决你的问题,请参考以下文章

使用联合优化按查询分组

MySQL 性能调优——SQL 优化

如何为传感器网络设计 HBase 架构?

布局优化基于麻雀算法求解无线传感器网络布局matlab源码

布局优化基于麻雀算法求解无线传感器网络布局matlab源码

MySQL explain根据查询计划去优化SQL语句