我正在编写一个用于查看和管理传感器数据的应用程序。我可以拥有无限数量的传感器,每个传感器每分钟读取一次,并将值记录为(时间,值,sensor_id,location_id,[一堆其他双打])。
例如,我可能每1000分钟就有1000个传感器并收集数据,最终在一年后产生525,600,000行。多个用户(例如最多20个)可以绘制任何时间段的数据,在任何范围内放大和缩小,并一次向传感器的数据添加注释。用户还可以修改某些数据点,我需要跟踪原始数据并对其进行修改。
我不确定像这样的应用程序的数据库应该是什么样的!它应该只是一个表SensorData,具有time和sensor_id以及location_id的索引吗?我应该根据sensor_id对这个表进行分区吗?我应该每天将数据保存在每个传感器的文件中(例如.csv文件)并根据请求将它们加载到临时表中吗?我该如何管理注释?
我还没有决定使用DBMS(可能是MySQL或PostgreSQL)。但我的目的是在一般的应用程序中深入了解数据管理。
答案 0 :(得分:1)
我假设用户无法更改您显示的字段(时间,值,sensor_id,location_id),但隐含其他字段。
在这种情况下,我建议使用Version Normal Form。您命名的字段是静态的,也就是说,一旦输入,它们就永远不会改变。但是,许多用户可以更改其他字段。
您无法说明用户是看到所有用户的更改还是只看到他们自己的更改。我将假设所有用户都看到了所有更改。如果这个假设是错误的,你应该能够做出适当的改变。
首先,让我们解释版本范式。正如您将看到的,它只是第二范式的一个特例。
获取已命名字段的元组,重新排列以将键值组合在一起:
R1( sensor_id(k), time(k), location_id, value )
如您所见,location_id(假设传感器是可移动的)和值取决于生成该值的传感器和进行测量的时间。这个元组是在2nf。
现在要添加可更新字段:
R2( sensor_id(k), time(k), location_id, value, user_id, date_updated, ... )
但是可更新字段(包含在省略号中)不仅依赖于原始键字段,还依赖于user_id和date_updated。元组不再是2nf。
所以我们不将新字段添加到原始元组,而是创建一个规范化的元组:
R1( sensor_id(k), time(k), location_id, value )
Rv( sensor_id(k), time(k), user_id(k), date_updated(k), ... )
这使得每个原始阅读都可以有一系列任意数量的版本。
查询特定阅读的最新更新:
select R1.sensor_id, R1.time, R1.location_id, R1.value, R2.user_id, R2.date_updated, R2.[...]
from R1
left join Rv as R2
on R2.sensor_id = R1.sensor_id
and R2.time = R1.time
and R2.date_updated =(
select max( date_update )
from Rv
where sensor_id = R2.sensor_id
and time = R2.time )
where R1.sensor_id = :ThisSensor
and R1.time = :ThisTime;
要查询特定用户所做特定阅读的最新更新,只需将user_id值添加到主查询和子查询的过滤条件即可。应该很容易看到如何获取特定阅读的所有更新或仅由特定用户进行的更新。
这种设计在如何访问数据方面非常灵活,并且由于关键字段也被编入索引,因此即使在非常大的表上也非常快。
答案 1 :(得分:0)
寻找答案我遇到了这个帖子。虽然它与我的情况并不完全相同,但它回答了我的许多问题;比如使用关系数据库这是一种合理的方法(答案是"是"),以及如何处理分区,维护,存档等。