2

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

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

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

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

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)

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

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

4

2 回答 2

7

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

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

有了足够强大的 DBMS,您就可以吃到自己的蛋糕——例如,Oracle 物化视图可以为您“预先加入”数据,而无需对实际数据模型进行非规范化处理。

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


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

在此处输入图像描述

revision_no当您在给定文章下添加修订时,该值会单调增长。

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

于 2012-04-11T19:54:31.680 回答
5

性能论点是无稽之谈-您做JOIN的 s 少,但 RDBMS 已针对JOINs 进行了优化。

但是,您可能会从服务器中提取必要更多的数据,这是无法优化的。

您还可能存在一致性问题。在不同表中复制同一项目的数据会导致出现不一致的情况。如果修订记录和文章记录的formator值不同author怎么办?你怎么知道哪个是正确的?如果contentinArticles与任何修订不匹配怎么办?

你真的应该把它标准化。我会CurrentRevision在您的表格中添加一个字段以Articles链接到当前版本,并且您应该ArticleIDRevisions表格中有一个字段将两者链接在一起。

于 2012-04-11T19:14:30.950 回答