【问题标题】:Database design for IoT application物联网应用的数据库设计
【发布时间】:2020-11-29 00:20:15
【问题描述】:

我们的应用程序为客户的远程设备显示近乎实时的物联网数据(最多 5 分钟间隔)。

最初的试点项目始终将每个设备读数存储在 SQL Server 2008 数据库上的简单“测量”表中。 该表如下所示:

Measurements: (DeviceId, Property, Value, DateTime).

在一两年内,每个设备的表中可能会有 100,000 条记录,查询通常分为两类:

  • “设备最新值”(95% 的查询):仅查看最新值
  • “设备每日快照”(5% 的查询):查看每天的单个代表值

我们现在正在扩展到 5000 台设备。 Measurements 表现在很小,但对于这 5000 台设备,很快就会有 50 亿条左右的记录。

该应用程序的读取量非常大,经常运行的查询尤其关注“设备最新值”。

[编辑 #1:减少基于意见的内容]

我们可以使用哪些数据库设计技术来优化“最新”物联网值的快速读取,给定一张包含多年“历史”物联网值的大表?

我们团队的一个建议是将MeasurementLatestMeasurementHistory 存储为两个单独的表。

[编辑#2:回应反馈]

在我们的测试数据库中,以 5000 万条记录为种子,并应用了以下索引:

CREATE NONCLUSTERED INDEX [IX_Measurement_DeviceId_DateTime] ON Measurement (DeviceId ASC, DateTime DESC)

一个典型的“获取设备最新值”查询(例如下面)仍然需要超过 4,000 毫秒才能执行,这对于我们的需求来说太慢了:

SELECT DeviceId, Property, Value, DateTime
FROM Measurements m
WHERE m.DateTime = (
  SELECT MAX(DateTime) 
  FROM Measurements m2
  WHERE m2.DeviceId = m.DeviceId)

【问题讨论】:

  • 虽然它仍然太宽泛,但您的问题没有一个答案(这是 SO 的前提),有多种可能性,每种可能性都可以很好地解决问题。事实上,没有任何迹象表明您当前的设计(具有正确的索引等)会表现不佳。

标签: sql-server database-design iot database-performance


【解决方案1】:

这是一个非常广泛的问题 - 因此,您不太可能得到明确的答案。

但是,我也遇到过类似的情况,我将介绍我的想法和最终的方法。总而言之 - 我做了选项 B,但在某种程度上反映了选项 A:我使用过滤索引来“模仿”单独的小表。

我最初的想法是有两个表格 - 一个包含“仅最新数据”用于大多数报告,然后一个表格包含所有历史值。另一种方法是有两个表 - 一个包含所有记录,一个包含最新记录。

当插入一个新行时,它通常需要更新至少两行,如果不是更多的话(取决于它的存储方式)。

相反,我选择了一条略有不同的路线

  • 将所有数据放在一张表中
  • 在该表上,添加一个新列“Latest_Flag”(位、非空、默认 1)。如果为 1,则为最新值;否则就是历史性的
  • 在包含所有列(具有适当的列顺序)的表上有一个 filtered index,并且过滤器 Latest_Flag = 1
    • 此过滤索引类似于仅包含最新行的表的第二个副本
  • 因此,插入过程在事务中有两个步骤
    • “取消标记”该设备的最后一个 Latest_Flag 等
    • 插入新行

它仍然使写入速度稍慢(因为它需要进行多次行更新以及索引更新),但从根本上说,它会为以后的读取进行预计算。

但是,当从表中读取时,您需要指定WHERE Latest_Flag = 1。或者,您可能希望将其放入视图或类似的视图中。

对于过滤后的索引,可能是这样的

CREATE INDEX ix_measurements_deviceproperty_latest 
    ON Measurements (DeviceId, Property)
    INCLUDE (Value, DateTime, Latest_Flag)
    WHERE (Latest_Flag = 1)

注意 - 另一个版本可以在触发器中完成,例如,当插入新行时,它会使任何先前的行无效(设置 Latest_Flag = 0)。这意味着您不需要进行两步插入;但是您确实依赖于触发器中的业务/处理逻辑。

【讨论】:

  • 谢谢@seanb - 我以前没有听说过过滤索引 - 它们非常适合这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多