2010-09-10 72 views
10

我和我的朋友正在建立一个网站,并有重大分歧。该网站的核心是一个关于“人”的评论数据库。基本上人们可以输入评论,他们可以输入评论的人。然后观众可以在数据库中搜索评论中的单词或人名的部分内容。它完全由用户生成。例如,如果有人想发表对某人姓名的拼写错误版本的评论,他们可以,而且没关系。因此,可能会有多个不同人物的拼写被列为几个不同的条目(一些中间名,一些昵称,一些拼写错误等),但这一切都可以。我们不在乎人们是否对随机的人或想象中的人发表评论。不必要的标准化

无论如何,问题是关于我们如何构建数据库。现在,它只是一个表注释ID作为主键,再有就是对“人”的注释字段约为:

评论ID - 评论 - 人

1 - “他很奇怪” - 约翰·史密斯

2 - “臭丫头” - 珍妮

3 - “同性恋” - 约翰·史密斯

4 - “欠我$ 20” - Jennyyyyyyyyy

一切工作正常。使用数据库,我可以创建列出特定“人员”的所有“评论”的页面。但是,他着迷于数据库没有正常化。我读了正常化,并了解到他错了。表格IS目前已经规范化,因为评论ID是唯一的并且决定了'评论'和'人员'。现在他坚持认为'人'应该拥有自己的桌子,因为这是'事情'。我不认为这是必要的,因为即使'人'真的是更大的容器(一个'人'可以对他们有很多'评论'),数据库似乎运行得很好,'人'是属性评论ID。我针对不同的SQL选择使用了各种PHP调用,使其在输出中以神奇的方式显得更加复杂,用户可以通过不同的方式搜索并查看结果,但实际上,安装非常简单。我现在让用户用竖起大拇指向下排列评论,并在同一张桌子上保留一个“分数”作为另一个字段。

我觉得目前没有必要为独特的“人物”条目设置单独的表格,因为“人物”没有自己的“分数”或他们自己的任何属性。只有评论可以。我的朋友是如此坚持以至于有效率。最后,我说:“好的,如果你想要我创建一个单独的表并让'person'成为它自己的字段,那么第二个字段是什么?因为如果一个表只有一列,那么看起来毫无意义。我们以后可能会创造一个需要给予'人'它自己的桌子,但我们可以处理那个。“然后他说,字符串不能是主键,并且我们会将当前表中的'persons'转换为数字,并且这些数字将成为新'person'表中的主键。对我而言,这看起来没有必要,它会使当前的表更难以阅读。他还认为,以后不可能创建第二张表格,而且我们现在需要预测我们以后可能需要它。

谁是对的?

回答

9

在我看来,你的朋友是对的。

人应该生活在不同的表中,你应该尝试正常化。不过,不要过度。

从长远来看,您可能希望在网站上做更多的事情,比如说要将多个文件附加到某个人(即,图片),你会非常感谢,然后为正常化。

+0

我同意弗兰基/你的朋友。以后做这种改变虽然不是不可能,但是很尴尬,容易出错。 – Jaydee 2010-09-10 15:41:26

+2

任何人都可以解释如何为任何功能依赖性的左侧没有出现的属性创建代理键来标准化数据库吗?正如OP所说,Person决定什么都不会(并且永远不会)。你会为名为'Stuff'的属性提供相同的建议吗?这里可能有一个正常化问题,但它不涉及Person。 – NealB 2010-09-10 20:47:37

+0

@NealB我作为一名教师的经历以及提问的方式让我相信OP是有偏见的。简单的事实是,该字段称为人而不是文本,与IMO相关。 – Frankie 2010-09-10 22:03:24

3

我会投你的朋友。我喜欢规范化和规划未来,即使你从不需要它,这种规范化过程也非常容易,而且不需要花费时间。您可以创建一个查询视图,以使您的SQL更清晰,并且无需您自己加入表。

0

这是交易。每当你创造一些东西时,你都要确保它有成长的空间。您想尝试预测未来的项目以及您计划的未来进展。在这种情况下,你说得没错,现在不需要添加一个持有1个字段的人表(不包括ID,假设你有一个int ID字段和一个人名)。但是,将来您可能希望为这些人提供其他属性,例如名字,姓氏,电子邮件地址,添加的日期等。

尽管过度规范化肯定是有害的,但我个人会创建另一个,更大的桌子可以容纳带有其他字段的人员,以便我可以在未来轻松添加新功能。

+1

是不是真的很难在稍后时刻将所有'独特'条目从'person'中拉出来,并将它们作为新表中的一列?并使用字符串作为主键有问题吗? – 2010-09-10 16:05:13

+1

使用字符串作为你的PK只会让事情变得更加困难。大量的DBMS允许你使用自动递增的数字ID,所以你并不需要关心发生错误的可能性。具有数字ID而不是字符串更有意义。 – Aaron 2010-09-10 20:36:52

1

那么,有两种思想流派。有人说,尽可能以最标准化的方式创建数据模型,然后在需要更高效率时取消规范化。另一个基本是“做这项工作所需的最低工作,然后根据你的要求改变”。也被称为YAGNI(你不需要它)。

这一切都取决于你看到了这一切。如果这是全部,那么你的方法可能很好。如果你打算随着时间推移改进它的新功能,那么你的朋友是对的。

2

你说得对。

Person可能是一般的事情,但不是在你的模型。如果你打算让人们正确地识别他们正在谈论的人,那么需要一个Person表。例如,如果评论仅针对已经在数据库中注册的人员。

但在这里它看起来像你有一个非结构化数据,而无需识别;并没有什么/没有人有兴趣确定“jenny”和“jennyyy”是否实际上是同一个人,更不用说“jenny doe”和“我的表弟”...

7

创建一个新表人和使用该表的关键字代替人的属性与标准化无关。由于其他原因,这可能是一个好主意,但这样做并不会使数据库“更规范化”而不是不这样做。所以你是对的:就标准化而言,创建另一个表是不必要的。

1

标准化是所有关于函数依赖(FD的)。在完全标准化之前,您需要确定数据模型属性中存在的 FD的全部

让审核你有什么:

  • 一个CommentId的任何给定的情况下功能决定了Person(FD:CommentId - >Person
  • 一个CommentId的任何给定的情况下功能决定了Comment(FD: CommentId - >Comment
  • 任何给定的CommentId实例在功能上决定了UserId(FD: CommentId - >UserId
  • 一个CommentId的任何给定的实例功能确定Score(FD:CommentId - 这里>Score

一切都是单独CommentIdCommentId从属属性。这可能导致您认为包含上述属性的全部或部分属性的关系(表格)必须进行标准化。

首先要问自己的是,为什么您创建了CommentId属性呢?严格来说, 这是一个制造的属性 - 它不涉及任何'真实'。 CommentId是 通常被称为代理键。代理键只是一个组成的值,其值为 ,表示与其他一组属性相对应的唯一值集合。那么CommentId 是什么样的属性呢?我们可以明白这 出通过提出下列问题,并增加新的FD对模型:

  • 1)评论是否必须是唯一的?如果是这样,FD:Comment - >CommentId必须为真。
  • 2)只要是关于不同的人,可以多次进行相同的评论?如果是,则 FD:Person + Comment - >CommentId必须为真,并且上面1中的FD是错误的。
  • 3)可以同一个评论多次提出关于同一个人提供的 不同UserId的?如果是,则1和2中的FD不能为真,但是 FD:Person + Comment + UserIdCommentId可能是对的。
  • 4)可以通过同一个UserId对同一个人进行多次相同的评论,但 有不同的评分?这意味着FD:Person + Comment + UserId'+ Score - >CommentId是真的,其他人是假的。

上面的4个FD中的一个必须是真的。无论它是否影响数据模型的标准化。

假设FD:Person + Comment + UserId - >CommentId证明是正确的。逻辑 后果是:

  • Person + Comment + UserIdCommentId服务方面等同键Score
  • Score应放在关系与之一,但不是它的键都(以避免传递依赖)。 明显的选择是CommentId,因为它是专门创建的替代品。
  • 甲关系组成:CommentIdPersonCommentUserId被扎 关键其替代需要。

从理论的角度来看,是不是 所需的代理键CommentId,让您的数据模型和数据库工作。然而,它的存在可能会影响关系的构建。

创建代理键是一个很重要的实际问题。 考虑,如果你选择不使用代理键,但全 属性在其位置设置Person + Comment + UserId可能发生的事情,尤其是当它需要在多个表的外键或主键 :

  • 注释可能会将多个空间开销 添加到您的数据库,因为它在多个表中重复。它可能不止是几个字符长。
  • 如果有人选择编辑评论,会发生什么?该更改需要传播 到注释是密钥一部分的所有表。不是一个美丽的景象!
  • 索引长期复杂的按键会占用大量的空间和/或作出更新缓慢性能

分配给代理键不会改变,无论你做什么,相关的属性值 值它确定。现在更新从属属性 限于定义代理键的一个表。这具有巨大的现实意义。

现在回到您是否应该创建Person的替代品。 Person在许多或任何FD的左侧是否存在 ?如果确实如此,它的价值将通过你的数据库传播,并且有一种情况可以为它创建一个替代品。 Person是文本还是数字属性与创建代理键的选择无关。

根据你所说的,最好的办法是创建一个 替代品Person。这种说法是基于怀疑它的价值可能在某个时候成为未来某个关键点或关键点的一部分。

1

如果您从不打算将person列与用户或其他任何事物相关联,并且数据显然不需要一致性或数据完整性检查,那么为什么这是关系数据库呢?这不是一个nosql数据库的用例吗?或者我错过了什么?

0

无论您何时与用户打交道,都应该有专门的表格。然后,您可以加入表格并引用该用户的ID。

user -> id | username | password | email 

comment -> id | user_id | content 

SQL加入评论的用户:

SELECT user.username, comment.content FROM user JOIN comment WHERE user.id = comment.user_id; 

这将使其在未来变得更轻松,当你想找到有关该特定用户的信息。额外的努力量可以忽略不计。

关于每个评论的“评分”,这也应该是一个单独的表格。这样你可以将用户连接到“喜欢”或“不喜欢”。

0

有了这个数据库,你可能会觉得它没问题,但是当你希望用户从数据库中知道更多信息时,将来可能会有一些问题。假设你想知道关于一个人的评论数量名字='abc'。在这种情况下,你将不得不浏览整个评论表并且继续计数。在这个位置,你可以为每个人设置一个名为'count'的属性,并且每当评论时就增加它是在那个人身上制造的。
就规范化而言,拥有规范化数据库总是会更好,因为它可以减少冗余并使数据库直观易懂。如果您预计未来您的数据库将会变大,那么标准化必须存在。