sql - 规范化或非规范化以在 RDBMS 中存储修订历史?

标签 sql database-design schema rdbms

我有一个基本的 CRUD 网络应用程序,人们可以在其中创建文章/编辑它们。我现在想添加保留所有编辑的修订历史的功能。目前,我有一个如下所示的文章表:

Article(id, title, content, author_id, category_id, format)

我考虑了 2 个选项来更改我当前的架构以添加对修订历史记录的支持。基本思想是对任何文章的每一次编辑都作为一条记录存储在修订表中。所以 Articles 和 Revisions 是一对多的关系。

第一个选项(规范化): 一张表用于文章元数据,一张用于修订。没有存储重复数据。

Article(id, title, category_id)
Revision(id, content, author_id, format)

第二个选项(去规范化): 两个表与选项 1 类似,但有一些重复的列。

Article(id, title, content, author_id, category_id, format)
Revision(id, article_id, content, author_id, format)

我正在考虑使用第二个选项,因为它会使我的编码更容易(不那么复杂,代码行数更少)。我知道这不是“学术”和“纯粹”的,但我个人的感觉是必须进行额外的连接会损害代码维护。此外,性能应该更好,因为不必完成那么多的连接。

这是完成这项任务的合理方法吗?我可能忽略了任何不可预见的或长期的后果?

最佳答案

如果你关心你的数据,你不会在“非规范化”的情况下以更少的代码结束 - 你必须强制 Revision 中的最新行始终与 中的副本匹配>文章。这在并发环境中实际上远非微不足道 - 您必须非常小心地进行锁定!

(如果您选择 RevisionArticle 不包含相同的副本,那么情况更糟 - 您将无法依赖 DBMS用于强制执行 Revision 主键!)

有了足够强大的 DBMS,您就可以吃蛋糕和吃它了 - 例如,Oracle 实体化 View 可以为您“预连接”数据,而无需对实际数据模型进行非规范化。

即使您没有这样的 DBMS,也只有在您测量实际数据量的性能后才考虑反规范化。是的,JOINS 可能很昂贵,但在您的特定情况下它们昂贵了吗?只有测量才能告诉我们。


顺便说一句,考虑像这样使用识别关系/自然键:

enter image description here

revision_no 随着您在给定文章下添加修订而单调增长。

Revision PK 下的 B-Tree 结构使得查找给定文章的最新(或任何!)修订版变得非常高效。除非您的问题中没有显示备用键,否则您也可以 cluster Revision 和(在 Oracle 下)甚至压缩了集群索引的前沿,因此重复 article_id 的空间开销被取消了。

关于sql - 规范化或非规范化以在 RDBMS 中存储修订历史?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10112322/

相关文章:

node.js - Mongoose 中的动态模式键

SQL: "... WHERE result<4.0"如果 'result' 是: "15.2","UNK","1.4"?

sql - 在 Oracle 中混合绑定(bind)变量和文字

database - AngularJS:我需要了解数据库结构才能实现吗?

mysql - 表特定查询与单个通用查询

sql - 在数据库中保存动态列表的首选方法是什么?

python - 用户不存在并且没有重定向到 django 项目中创建的租户

java - 使用 JDBC 和唯一约束批量插入

python - Sqlite3 通过提供年和月搜索列

javascript - 为什么在 Mongoose 模式中嵌套对象?