database-design - 在 SQLAlchemy 中使用数组的替代方法
问题描述
我们有一个使用 sqlalchemy 创建的数据库,其中包含这些表(以及其他):
users alarms alarm_history
+---------+-----------+ +----------+------------+ +----------+-----------+------------+
| user_id | user_name | | alarm_id | alarm_name | | alarm_id | timestamp | alarm_data |
+---------+-----------+ +----------+------------+ +----------+-----------+------------+
可能值得指出的是,这些表中还有很多其他数据,这是一个缩写版本,alarm_id 是通过外键关联的。还有许多其他具有关系的表。
Alarms 表就像要监控的警报的主列表,History 表只是从外部监控服务接收到的警报数据的历史更改列表,而 users 表是不言自明的。
我们需要做的是有一个用户订阅的警报的默认列表(由于他们所属的组),而且还能够选择订阅或取消订阅哪些警报。这必须是可即时管理的——他们可以随时通过 API 进行更改。
我应该如何将这些配置存储在数据库中?然后的想法是在用户表中有一个“订阅”列,它指向它需要用来确定用户需要监控的警报集的配置。
- 我考虑在警报表中添加一个订阅列,它只是一个订阅的 ID 的数组/列表,但 SQL 不存储数组或列表。
- 我也想过有一个配置表,详细说明每个配置的名称和它关心的警报,但是你遇到了同样的问题——如果没有数组/列表,你如何告诉它它引用了哪些警报?
- 我还考虑过每次有人创建新配置时生成一个新表,但阅读告诉我这是一个非常糟糕的主意,我什至不知道如何做这样的事情。
- 我还考虑过使用该方法在数据库查询中解析一个列表
IN(<list>)
,但是当列表长于 ~900 个元素时会出现内存错误,因此您需要批处理请求。另外,它不是真正的关系,所以它很慢。
有关如何解决此问题的任何指示?
解决方案
数组很少在 RDBMS 中使用。原因很明显:关系数据库系统已经将关系存储在表中,那么为什么要添加仅表示 1:n 关系的数组而没有外键一致性和快速索引查找的数据库优势呢?
你说一个用户属于一个组甚至组(这不清楚)。所以我期待一个组表。如果用户属于一个组,您将group_id
在用户表中添加一个。如果用户可以属于多个组,您将添加一个user_group
桥接表。
组具有默认警报。由于一个组可以有多个默认警报,而一个警报可能是多个组的默认警报,因此您将有一个 m:n 关系,这意味着一个桥接表group_alarm
。
用户最终决定订阅哪些警报。另一个 m:n 关系,另一个桥表:user_alarm
.
到目前为止,对于数据库结构来说,这已经足够简单了。
现在回到逻辑:您希望默认订阅警报。这意味着您在将组分配给用户时将默认警报分配给用户。这可以通过将警报从应用程序复制group_alarm
到user_alarm
应用程序或由应用程序复制的触发器来完成。触发器会自动且无声地执行此操作。应用程序也可以静默执行此操作,也可以提供复选框列表,因此可以显式完成订阅/取消订阅。
当警报作为默认值添加到组时,我想您不希望发生任何事情。我想这只会影响新的用户/组关联。或者您想将此警报添加到用户警报中吗?如果是这样,再次触发可能是合适的。
我不知道 SQLAlchemy。它是一个 ORM,并且 ORM 倾向于尝试将 RDBMS 提供的关系网络转换为树结构,这必然会导致妥协,包括不太方便和更慢的数据访问。突然之间,您被迫使用单纯的编程语言来查询数据,而不是使用 4GL 查询语言。因此,虽然上述结构是合适的数据库,但我不知道在 SQLAlchemy 中使用它会有什么感觉。
推荐阅读
- haskell - 获取数据类型中的键的最佳方法是什么?
- graphql - 在 GraphQl 中定义解析器
- google-apps-script - 跨多个工作表更改多个用户的权限
- c - 套接字 recv() 只接收 1 个字节的数据
- plist - What does this suspicious plist data state
- jmeter - How do I fix JMeterPluginsCMD "Exception in thread "main" java.lang.ExceptionInInitializerError" error
- uipath - How to get index of the cell value in UiPath
- azure - Azure CI 管道中的构建错误,因为某些项目位于不同的存储库中
- databricks - databricks 从 s3 存储桶路径参数加载文件
- javascript - 求矩阵/二维数组的 N 次遍历