Sql 关于传感器/读数/警报数据库设计的意见

Sql 关于传感器/读数/警报数据库设计的意见,sql,database,database-design,relational-database,Sql,Database,Database Design,Relational Database,最近我问了一些关于数据库设计的问题,可能太多了;-)然而,我相信,我正在慢慢地触及我的设计的核心,并慢慢地将其煮沸。关于如何将“警报”存储在数据库中,我仍在绞尽脑汁做几个决定 在这个系统中,警报是一个必须被确认、采取行动等的实体 最初,我将读数与如下警报相关(非常精简):- 最后一个表将读数与警报关联,因为正是读数指示传感器是否处于警报状态 这种设计的问题在于,它允许来自多个传感器的读数与单个警报相关联,而每个警报仅针对单个传感器,并且应该仅具有与之相关的传感器读数(我是否应该担心DB允许这种情

最近我问了一些关于数据库设计的问题,可能太多了;-)然而,我相信,我正在慢慢地触及我的设计的核心,并慢慢地将其煮沸。关于如何将“警报”存储在数据库中,我仍在绞尽脑汁做几个决定

在这个系统中,警报是一个必须被确认、采取行动等的实体

最初,我将读数与如下警报相关(非常精简):-

最后一个表将读数与警报关联,因为正是读数指示传感器是否处于警报状态

这种设计的问题在于,它允许来自多个传感器的读数与单个警报相关联,而每个警报仅针对单个传感器,并且应该仅具有与之相关的传感器读数(我是否应该担心DB允许这种情况?)

我想,为了简化事情,为什么还要麻烦阅读表格呢?相反,我可以这样做:

[Location]
LocationId

[Sensor]
SensorId
LocationId

[SensorReading]
SensorReadingId
SensorId
Value
Status
Timestamp

[SensorAlert]
SensorAlertId
SensorId
Timestamp

[SensorAlertEnd]
SensorAlertId
Timestamp
基本上,我现在并没有将读数与警报联系起来——相反,我只知道警报在特定传感器的开始和结束时间之间处于活动状态,如果我想查找该警报的读数,我可以这样做

显然,缺点是我不再有任何约束阻止我删除警报期间发生的读数,但我不确定该约束是否必要

现在,从外部看,作为一名开发人员/DBA,这会让你感到恶心吗?或者这看起来合理吗

有没有其他我可能不知道的方法

谢谢

编辑: 这里还有一个想法——它以不同的方式工作。它将每个传感器状态的变化(从正常状态到警报状态)存储在一个表中,然后读数仅与特定状态关联。这似乎解决了所有的问题-你认为呢?(我唯一不确定的是将表命名为“SensorState”,我不禁想到还有更好的名称(可能是SensorReadingGroup?):-

必须有一个优雅的解决方案!

您必须处理的主要“三角形”是传感器、[传感器]读数和警报。假设您必须跟踪正在发生的活动(而不是“一次加载所有内容”的设计),您的第三个解决方案与我们最近所做的类似。稍作调整,它看起来会像:

[Location] 
LocationId 

[Sensor] 
SensorId 
LocationId 
CurrentSensorState  --  Denormalized data!

[SensorReading] 
SensorReadingId 
SensorState
Value 
Timestamp 

[SensorStateLog] 
SensorId 
Timestamp 
SensorState
Status   --  Does what?
IsInAlert 
(Primary key is {SensorId, Timestamp})
“SensorState”可以是SensorStateId,并带有一个相关联的查找表,列出(并约束)所有可能的状态

想法是,每个传感器包含一行,并显示其当前状态。传感器读数随传感器读数不断更新。如果给定传感器的当前状态发生变化(即新读数的状态与传感器的当前状态不同),则,您可以更改当前状态,并在SensorStateLog中添加一行,显示状态的更改。(可选地,您可以使用“状态结束”时间戳更新该传感器的“Previor”条目,但这是需要编写的繁琐代码。)

传感器表中的CurrentSensorState是非规范化数据,但如果正确维护(如果有数百万行),则查询当前状态的效率将大大提高,因此可能值得付出努力


所有这些的明显缺点是警报不再是一个实体,它们变得更难跟踪和识别。如果这些警报必须易于识别和使用,那么您的第三个方案将无法完成您需要它完成的任务。

这是我对这个问题的两分钱

AlertType表格包含所有可能的警报类型。
AlertName
可能是高温、低压、低水位等

警报设置表格允许从传感器设置特定警报类型的警报阈值。 例如,
TresholdLevel
=100和
TresholdType
='HI'应触发读数超过100的警报

读取表在传感器读数流入服务器(应用程序)时保存传感器读数

警报表格保存所有警报。它保留指向触发警报的第一次读取和最后一次读取的链接(
FirstReadingId
LastReadingId
)。
如果(
SensorId
AlertTypeId
)存在活动警报,则为“激活”
组合。
IsActive
只能通过读取低于警报阈值的值才能设置为false。
isackknowledged
表示操作员已确认警报

  • 应用程序层将新的读取插入读取表,捕获
    读取ID

  • 然后应用程序根据每个(
    SensorId
    AlertTypeId
    )组合的警报设置检查读数。此时将创建对象集合
    {SensorId,AlertTypeId,ReadingId,IsAlert}
    ,并为每个对象设置
    IsAlert
    标志

  • 然后检查警报表中集合中每个对象
    {SensorId、AlertTypeId、ReadingId、IsAlert}
    的活动警报

    • 如果
      IsAlert
      为真,并且(
      SensorId
      AlertTypeId
      )没有激活的警报组合后,将一个新行添加到警报表中,其中
      FirstReadingID
      指向当前
      ReadingId
      。将
      IsActive
      设置为TRUE,将
      isackknowledged
      设置为FALSE

    • 如果
      IsAlert
      为真且(
      SensorId
      AlertTypeId
      )组合存在活动警报,则通过设置指向当前
      ReadingId
      LastReadingID
      来更新该行

    • 如果
      IsAlert
      为假,并且(
      SensorId
      [Location] LocationId [Sensor] SensorId LocationId [SensorState] SensorStateId SensorId Timestamp Status IsInAlert [SensorReading] SensorReadingId SensorStateId Value Timestamp
      [Location] 
      LocationId 
      
      [Sensor] 
      SensorId 
      LocationId 
      CurrentSensorState  --  Denormalized data!
      
      [SensorReading] 
      SensorReadingId 
      SensorState
      Value 
      Timestamp 
      
      [SensorStateLog] 
      SensorId 
      Timestamp 
      SensorState
      Status   --  Does what?
      IsInAlert 
      (Primary key is {SensorId, Timestamp})
      
      INSERT Sensor VALUES (
          @LocationId,
          SensorNo = ( SELECT ISNULL(MAX(SensorNo), 0) + 1
              FROM Sensor
              WHERE LocationId = @LocationId
              )
          @SensorCode
          )
      -- Assume @LoopDateTime contains the DateTime of the last iteration
      INSERT Alert
          SELECT LocationId,
                 SensorNo,
                 ReadingDtm,
                 "L"          -- AlertType "Low"
              FROM Sensor  s,
                   Reading r
              WHERE s.LocationId = r.LocationId
              AND   s.SensorNo   = r.SensorNo
              AND   r.ReadingDtm > @LoopDtm
              AND   r.Value      < s.LowerLimit
      INSERT Alert
          SELECT LocationId,
                 SensorNo,
                 ReadingDtm,
                 "H"          -- AlertType "High"
              FROM Sensor  s,
                   Reading r
              WHERE s.LocationId = r.LocationId
              AND   s.SensorNo   = r.SensorNo
              AND   r.ReadingDtm > @LoopDtm
              AND   r.Value      > s.UpperLimit