4

我正在尝试决定数据库设计。更具体地说,这是更大设计的子部分。基本上,有“位置”——每个位置可以有任意数量的传感器与之关联,它可以有一个记录器(但只有 1 个)。

我有传感器读数和记录仪读数,每个读数都足够不同,我认为需要单独的表格。

如果传感器读数超出范围,则会生成警报。虽然传感器读数超出范围,但它们仍与该警报相关联,因此您最终会收到 1 个包含许多读数的警报,以便我稍后绘制警报图,以便发现趋势等。

与记录仪读数相同。

到目前为止,这是我存储这些数据的 3 个想法:

选项1:

位置[表]
- 身份证 [PK]
- 姓名
- 有记录器

LiveSensor [表格]
- 位置 ID [FK]
- 身份证 [PK]

LiveSensorReading [表格]
- 身份证 [PK]
- 传感器 ID [FK]
- 价值

LiveSensorAlert [表格]
- 身份证 [PK]
- SensorReadingId [FK](可能不需要 - 强制要求始终至少有 1 个读数)

LiveSensorAlertCorrectiveAction [表]
- LiveSensorAlertId [FK]
- CorrectiveActionId [FK]
- 按用户 ID [FK]

LiveSensorAlertAcknowledgement [表]
- LiveSensorAlertId [FK]
- 按用户 ID [FK]

LiveSensorAlertReading [表]
- SensorAlertId [FK]
- SensorReadingId [FK]

LoggerReading [表]
- 位置 ID [FK]
- 价值

LoggerAlert [表]
- 身份证 [PK]
- LoggerReadingId [FK](可能不需要 - 强制要求始终至少有 1 个读数)

LoggerAlertReading [表]
- LoggerAlertId [FK]
- LoggerReadingId [FK]

LoggerAlertCorrectiveAction [表]
- LoggerAlertId [FK]
- CorrectiveActionId [FK]
- 按用户 ID [FK]

LoggerAlertAcknowledgement [表]
 - LoggerAlertId [FK]
 - 按用户 ID [FK]
  • 问题:很多重复的表格(这真的很重要吗??)

选项 2:

位置[表]
- ID
- 姓名
- 有记录器

传感器 [表]
- 身份证 [PK]
- 位置 ID [FK]

SensorReading [表格]
- 身份证 [PK]
- 传感器 ID [FK]
- 价值

记录仪阅读
- 位置 ID [FK]
- 价值

警报 [表格]
- 身份证 [PK]

AlertCorrectiveAction [表]
- 警报 ID [FK]
- CorrectiveActionId [FK]
- 按用户 ID [FK]

AlertAcknowledgement [表]
- 警报 ID [FK]
- 按用户 ID [FK]

SensorAlertReading
- 警报 ID [FK]
- SensorReadingId [FK]

LoggerAlertReading
 - 警报 ID [FK]
 - LoggerReadingId [FK]
  • 问题:不强制执行“每个警报至少 1 个读数”规则。
  • 问题:允许不止一种类型的读数引用相同的警报。

选项 3:

位置[表]
- ID
- 姓名
- 有记录器

传感器 [表]
- 身份证 [PK]
- 位置 ID [FK]

SensorReading [表格]
- 身份证 [PK]
- 传感器 ID [FK]
- 价值

记录仪阅读
- 位置 ID [FK]
- 价值

提醒【表】“超级表”
- 身份证 [PK]

LoggerAlert [表]
- 警报 ID [PK,FK]
- LoggerReadingId [FK]

SensorAlert [表格]
- 警报 ID [PK,FK]
- SensorReadingId [FK]

AlertCorrectiveAction [表]
- 警报 ID [FK]
- CorrectiveActionId [FK]
- 按用户 ID [FK]

AlertAcknowledgement [表]
- 警报 ID [FK]
- 按用户 ID [FK]

SensorAlertReading [表格]
- SensorAlertId [FK]
- SensorReadingId [FK]

LoggerAlertReading [表]
 - LoggerAlertId [FK]
 - LoggerReadingId [FK]
  • 问题:没有什么能阻止 LoggerAlert 和 SensorAlert 引用相同的警报(与选项 2 相同的问题)。
  • 问题:混淆数据库(超级表不是更多的 OO 概念吗?数据库意味着纯粹是关系,不是吗?)

我认为到目前为止我更喜欢选项 1,因为它看起来很干净而且意图很明确(我希望!),即使我有效地重复表格。

我刚刚想到的唯一一个小问题是,不同传感器的读数仍然可能与一个警报相关联。

我想知道人们对上述选项的看法。我经常看到使用建议安静的“超级表”,但由于某种原因,它感觉不对 - 几乎感觉有点像黑客,尤其是当我看到试图确保数据完整性的方法时。它似乎更类似于 OO 编程而不是关系设计。

谢谢。

编辑: 一些进一步的信息,以帮助回答以下一些问题:

大多数情况下,数据库仅通过应用程序服务器进行操作,如果这有什么不同的话。

实时警报和记录器警报通常被视为相同,因此我可能会在大多数时间处理所有警报,而不是以不同的方式处理记录器警报和实时警报。

记录器在位置表中具有相当特定的列。由于位置和记录器将是一对一的映射,我决定不使用单独的记录器表,到目前为止,它似乎工作得很好并保持简单。示例列:LoggerRFID (int)、LoggerUpperLimit (float)、LoggerLowerLimit (float) 等。您几乎可以争辩说记录器是传感器,但我沿着这条路走下去,结果并不好。

我几乎可以接受将警报设为通用,但正如其中一个答案所说,我正试图对此非常确定,因此在选择特定路径之前尽可能长时间地继续研究。

4

3 回答 3

1

对此的一些想法(想法和意见,而不是答案):

“超级表”(类型/子类型)模型很有吸引力,但实施和支持可能很棘手。几个技巧:

ALERT
  AlertId    PK 1/2
  AlertType  PK 2/2  Check constraint (1 or 2, or better L or S)

...也就是说,复合主键,其中“类型”必须始终是 L)og 或 S)ensor。

LOGALERT
  LogAlertId  PK 1/2  FK 1/2
  AlertType   PK 2/2  FK 2/2

(and again for SENSORALERT)

...也就是说,相同的复合主键,外键在两列上。这样一来,给定的类型表只能有一个子类型表,并且顶部的表清楚地显示了涉及哪个子类型。无法强制子类型表中存在行,因此请仔细设置数据。并且大部分查询复杂性都可以使用视图来处理(掩盖?)。

不利的一面是,它很复杂,让那些(还)不熟悉它的人感到困惑,并且需要额外的支持和努力。真正的问题是,值得吗?

  • 您必须多久处理一次所有警报,不仅是日志还是传感器?如果大多数时候你只需要处理其中一个,那可能就不值得了。
  • 您需要处理多少特定​​于日志或传感器的详细信息?除了与单个警报相关的实际事件之外,您将要跟踪的无数属性(列中的详细信息)在这两种类型中的相似程度如何?如果用户、确认和纠正措施(足够)相同,您可以将它们设为 ALERT 的属性(列),但如果不是,则必须将它们设为适当子类型的属性,这样您就失去了超类型的整合优势。
  • 你现在必须在设计期间把它弄好。研究、提出问题、凝视水晶球(即思考未来可能发生的事情以使每个人当前的假设无效),因为如果你现在弄错了,你和你的继任者可能不得不永远忍受它。
于 2010-11-29T17:44:47.630 回答
1

我认为这个问题已经在你的另一个问题中得到了回答,完整的数据模型;否则(如果有任何未解决的问题),请发布对此问题的编辑。

如果你对Supertype-Subtype Relational 结构感兴趣,在一般意义上,这个问题你可能会感兴趣。

我可以建议你关闭这个问题。

于 2010-12-09T07:26:19.510 回答
1

您可以在选项一中将 ObjectType 列添加到镜像表中,并提供 Sensor 或 Logger 的值。您的数据库设计将如下所示:

Location [Table]
- Id
- Name
- HasLogger

ObjectType [Table]
- Id [PK]
- Name -- either Sensor or Logger
- Description

Object [Table]
- Id [PK]
- LocationId [FK]
- ObjectTypeId [FK]

Reading [Table]
- Id [PK]
- ObjectId [FK]
- Value

ObjectReading
- ObjectId [FK]
- ReadingId [FK]

Alert [Table]
- Id [PK]
- ReadingId [FK]

AlertCorrectiveAction [Table]
- AlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]

AlertAcknowledgement [Table]
- AlertId [FK]
- ByUserId [FK]

这种设计确实有点混淆了数据库的基本目的,主要是因为我想不出比“对象”更好的词来描述“传感器或记录器”——如果有一些特定的术语可以共同描述附加在位置,这肯定有助于理解数据库。

如果您对表中的非整数 ID 不是特别敏感,您也可以从 ObjectType 中删除 Id 列并将 Name 设置为主键。不过,我对像 ObjectType 这样主键不是整数的表有过不好的体验,所以我几乎总是使用一个。

我也同意上面 KM 的评估,即每个表的主键 ID 的名称应该比“Id”长。

于 2010-11-29T17:41:10.893 回答