重新设计数据库的机会:用于此传感器数据收集的表格设计如何?


13

背景

我有一个大约2000个传感器的网络,每个传感器都有大约100个数据点,我们每隔10分钟收集一次。这些数据点通常是int值,但有些是字符串和浮点数。此数据应存储90天,如果可能的话,还可以保留更长时间。

数据库设计

当最初负责该项目时,我编写了一个C#应用程序,该程序为每个传感器编写了逗号分隔的文件。当时没有那么多,当有人想查看趋势时,我们将在Excel中打开csv并根据需要绘制图形。

事情发展了,我们切换到了MySQL数据库。我为每个传感器创建了一个表格(是的,我知道很多表格!);它一直运行良好,但是有一些局限性。拥有如此多的表,显然不可能编写查询来查找特定值时在所有传感器中查找数据的查询。

对于下一个版本,我切换到Microsoft SQL Server Express,并将所有传感器数据放入一个大表中。这也有效,并且让我们进行查询以在所有感兴趣的传感器中查找值。但是,我遇到了Express版本的10GB限制,因此决定改回MySQL,而不是投资于SQL Server Standard。

问题

我对MySQL的性能和可伸缩性感到满意,但不确定是否坚持采用“一个表中的所有数据”方法是最好的。一张桌子上的10GB似乎要求使用其他设计。我应该提到仍然需要查询图形数据,而且我担心查询图形时会出现性能问题,例如,整个90天中一个传感器的温度数据。(换句话说,图形应该是可以快速生成的图形,而不必等待SQL对大量数据进行排序以隔离感兴趣的传感器。)

是否应该以某种方式拆分此表以提高性能?拥有这么大的桌子不是很平常吗?

我在Sensor ID和Timestamp列上都有索引,这几乎是任何查询的定义边界。(即从时间A到时间B获取传感器X的数据)。

我已经阅读了一些有关分片和分区的知识,但是在这种情况下,觉得不合适。


编辑:

根据到目前为止的评论和答案,一些其他信息可能会有所帮助:

不定期存储:目前,我不存储90天以上的数据。每天,我都会运行一个查询,以删除90天以上的数据。如果将来它变得很重要,我会存储更多,但现在就足够了。这有助于保持大小和性能更高。

引擎类型:原始的MySQL实现使用MyISAM。这次为新实现创建表时(一个数据表而不是多个数据表),它们默认为InnoDB。我不认为我需要其中之一。

标准化:当然,除了数据收集表外,还有其他表。这些支持表存储诸如传感器的网络信息,用户的登录信息等内容。据我所知,没有太多要标准化的东西。数据表具有如此多列的原因是每个传感器都有很多变量。(多个温度,光照水平,气压等)。对我进行归一化意味着没有冗余数据或重复的组。(至少对于1NF。)对于给定的传感器,在特定时间存储所有值需要一行数据,并且其中不涉及1:N关系(我知道)。

我可以在功能上分解表,例如在一个表中创建所有与温度相关的值,在另一个表中创建与气压相关的所有值。虽然这可能会提高仅进行温度查询的人员的效率,但我仍然必须一次插入所有数据。尽管如此,效率提高对于SELECT操作还是值得的。显然,最好根据用户请求数据的频率垂直拆分表。也许这就是我应该做的。我想在问我一个问题时正在寻求确认,这样做是值得的。


编辑2:

数据使用:最终,绝不会查看或需要很多数据,因为我们通常只关注有问题的项目。但是,在尝试发现问题时,我们使用各种工具来搜索数据并确定要放大的项目。

例如,我们注意到内存使用率值(特定于客户的专有软件程序)与重启/崩溃之间的相关性。我收集的数据点之一与此内存使用情况有关,并且我能够查看历史数据以显示超出特定内存使用量后设备变得不稳定。今天,对于运行该软件的部分设备,我检查了该值,如果该值过高,则发出重新启动命令。在发现这一点之前,我认为收集这些数据没有价值。

因此,我坚持要收集并存储大约100个数据点,即使该值值得怀疑。但是在正常的日常使用中,用户通常会检查其中的十几个参数。如果用户对特定地理区域感兴趣,则他(可以使用软件)可能会为几十个传感器生成数据的图形或电子表格。查看30天的图表并显示两条或三条显示温度,气压和光照水平等曲线的情况并不少见。这样做将运行类似于以下的查询:

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(在原始的MySQL版本中,每个传感器都有自己的表,将发出三个单独的查询,但结果将通过软件合并以创建图形。)

由于该data表包含很多行(〜1000万),尽管在id和上都有索引data_timestamp,所以性能明显比多表方案(9秒内返回4500行,而在此示例中不到1秒)要好。在多表模式中,找到哪些传感器满足特定条件的能力实际上为零,因此,移至单个表的原因。

这类查询可以由多个用户快速连续地完成,因为他们选择了不同的数据组并比较每个结果中的图形。每个图形或电子表格等待近10秒可能会令人沮丧。

90天后数据将被丢弃。可以将其存档,但当前不是必需的。

希望这些信息有助于更充分地显示收集和存储数据后的使用方式。


为了使该问题获得正确的答案,您可能应该扩展数据的实际使用方式。到目前为止,您在提供的信息深度方面处于领先地位,但您可能会从错误的角度提出问题。
Mark Storey-Smith'2

好的,@ Mark,我也会详细说明。我正试图不要有太长的问题,以免它会淹没。
JYelton 2012年

Answers:


5

您应该考虑对表进行分区的一个重要原因。

您在巨型表上拥有的所有索引,甚至只有一个索引,都可以产生大量CPU负载和磁盘I / O,仅在执行INSERT,UPDATE和DELETE时执行索引维护。

在2011年10月7日写了一篇较早的文章,主题是为什么表分区会大有帮助。这是我过去的帖子的摘录:

数据分区应用于对逻辑上和内聚性在同一类中的数据进行分组。只要将数据正确分组,搜索每个分区的性能就不必成为主要考虑因素。一旦完成了逻辑分区,就可以专注于搜索时间。如果仅按ID分隔数据,则可能永远无法访问多行数据进行读取或写入。现在,这应该是一个主要的考虑因素:找到最常访问的所有ID,并按此进行分区。所有访问频率较低的ID都应驻留在一个大的存档表中,对于“一次蓝月亮”查询,索引查找仍可访问该存档表。

您稍后可以阅读我的整个帖子

为了顺应这一趋势,您需要研究并找出10GB表中很少使用的数据。如果您需要对历史性进行临时查询,则应将数据放置在易于访问的存档表中。从10GB迁移该存档,然后OPTIMIZE TABLE从10GB的表迁移,可以使工作集更快地运行SELECT,INSERT,UPDATE和DELETE。甚至DDL在2GB工作集上的运行速度也要比10GB表快。

更新2012-02-24 16:19 EDT

需要考虑的两点

  1. 从您的评论看来,您可能需要标准化。
  2. 您可能需要将超过90天的所有内容迁移到存档表中,但仍同时访问存档和工作集。如果您的数据全部是MyISAM,则建议使用MERGE存储引擎。首先,一旦将工作集MyISAM表和归档MyISAM表结合在一起,就创建MERGE表映射。您将在一个MyISAM表中保留少于91天的数据,并将超过90天的任何数据过渡到存档中。您将仅查询MERGE表映射。

这是我关于如何使用它的两篇文章:

这是我在具有很多列的表上发表的另一篇文章

MySQL中的列过多


有些列的使用频率较低,但是所有传感器的关注度都差不多。因此,我可以想象垂直拆分表将是有利的。例如,一个20列的表(经常访问)和一个80列的表(很少访问)。我不确定这与分区相同。
JYelton

感谢您的修改。我阅读了有关“ MySQL中的列过多”的文章。我将用一些其他有用的观点来编辑我的问题。
JYelton

5

有趣的是...如果所有传感器都产生相同类型的数据,则将它们全部放在同一个表中确实很有意义,但是有了如此大量的数据,我可以理解为什么您会担心性能。

90天是您制作图表的通常时间吗?如果是这样,您可能有两个表:主传感器数据表,用于存储90天前(直到今天)的数据(如果需要一些余量,则要多一些),而所有旧数据都存储在存档表中。这可以帮助减少开始生成报告的表的大小,希望您10 GB的数据的大部分将在存档表中,而不是在主表中。可以将存档作业安排为每晚运行。

也许还可以考虑构建一个单独的报告数据库,该数据库以一种结构更好地存储数据,该结构更适合从中生成报告(为了更紧密地匹配您要查询的内容而设计的表,并可能预先计算和汇总值,否则将花费很长时间生成(如果可能的话),然后定期(例如每晚)从主数据库重新填充它。当然,如果您需要从最新数据生成的报告,则可能效果不佳。


此时无需存储超过90天的任何内容,但会很好。我同意最好将其存储在“存档”表中。图形和数据分析的范围从仅几个小时到整整90天。大多数制图要求仅使用过去一周左右的数据,但是90天制图很常见。我们的公司(尚未)要求提供更长的报告。
JYelton

@JYelton:您可以根据需要在此方法中使用任意多个层。最新的表格可能只有今天。下表可能是从今天到2周前。下表可能是从今天到90天之前的表格。最后一张桌子可以容纳一切。
FrustratedWithFormsDesigner 2012年

如果我正确理解您的意思,就是说要复制该表,但是要覆盖不同的时间段。因此,如果有人要求提供7天的报告,则将使用仅返回一周的表。如果然后扩展到8天,将使用第二大表(例如30天)吗?这无疑会提高较短持续时间的查询的速度,但会以存储(便宜)和处理分层表的编程逻辑为代价(不那么便宜)。
JYelton 2012年

@JYelton:是的,我认为您理解正确。如果查询时间范围是标准的(今天-1天,今天-7天,今天-30天,今天-90天),那么我认为这不会太困难,因为您将永远知道要使用哪个表击中。如果时间范围的长度可能不同,而范围的开始日期可能不是当前日期,那么您是正确的,实现逻辑将变得棘手,并且使用多表进行UNION操作可能会使跨表查询变得昂贵。
FrustratedWithFormsDesigner 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.