83

一位前同事坚持认为,具有更多表且每列更少的数据库比具有更少表且每列更多的数据库要好。例如,不是包含名称、地址、城市、州、邮编等列的客户表,而是名称表、地址表、城市表等。

他认为这种设计更加高效和灵活。也许它更灵活,但我没有资格评论它的效率。即使它更有效,我认为这些收益可能会被增加的复杂性所抵消。

那么,与具有更多列的更少表相比,具有更少列的更多表有什么显着的好处吗?

4

18 回答 18

66

在设计数据库时,我遵循了一些相当简单的经验法则,我认为它们可以用来帮助做出这样的决策......

  1. 赞成标准化。非规范化是一种优化形式,具有所有必要的权衡,因此应该以YAGNI的态度来处理它。
  2. 确保引用数据库的客户端代码与架构充分分离,从而无需对客户端进行重大重新设计。
  3. 当它为性能或查询复杂性提供明显的好处时,不要害怕去规范化。
  4. 当数据量和使用场景允许时,使用视图或下游表来实现非规范化,而不是非规范化模式的核心。

这些规则的通常结果是,最初的设计将偏爱表而不是列,重点是消除冗余。随着项目的进展和非规范化点的确定,整体结构将朝着平衡的方向发展,以牺牲有限的冗余和列扩散来换取其他有价值的好处。

于 2008-09-12T17:02:49.613 回答
12

我会赞成更多的桌子,但仅限于某一点。使用您的示例,如果您将用户的信息分成两个表,例如 USERS 和 ADDRESS,这使您可以灵活地为每个用户提供多个地址。一个明显的应用是具有单独帐单和送货地址的用户。

支持使用单独的 CITY 表的论点是您只需存储每个城市的名称一次,然后在需要时引用它。这确实减少了重复,但在这个例子中,我认为这是矫枉过正。它可能更节省空间,但是当您从数据库中选择数据时,您将在连接中付出代价。

于 2008-09-12T16:50:10.470 回答
11

这听起来不像是关于表格/列的问题,而是关于规范化的问题。在某些情况下,高度规范化(在这种情况下为“更多表”)是好的、干净的,但通常需要大量的 JOIN 才能获得相关结果。如果数据集足够大,这可能会降低性能。

Jeff 写了一些关于 StackOverflow 设计的文章。另请参阅Dare Obasanjo的帖子 Jeff 链接。

于 2008-09-12T16:48:42.970 回答
5

这取决于您的数据库风格。例如,MS SQL Server 往往更喜欢更窄的表。这也是更“规范化”的方法。其他引擎可能更喜欢它。大型机往往属于这一类。

于 2008-09-12T16:47:27.043 回答
5

完全规范化的设计(即“更多表”)更灵活、更易于维护并避免数据重复,这意味着您的数据完整性将更容易实施。

这些都是正常化的有力理由。我会选择先规范化,然后在您看到性能成为问题后才对特定表进行非规范化。

我的经验是,在现实世界中,即使有非常大的数据集,你也不会达到需要非规范化的地步。

于 2008-09-12T16:54:18.493 回答
5

每个表应仅包含与由主键唯一标识的实体相关的列。如果数据库中的所有列都是同一实体的所有属性,那么您只需要一个包含所有列的表。

但是,如果任何列可能为空,则需要将每个可为空的列放入其自己的表中,并使用主表的外键对其进行规范化。这是一种常见的情况,因此为了更简洁的设计,您可能会向现有表添加比列更多的表。此外,通过将这些可选属性添加到它们自己的表中,它们将不再需要允许空值,并且您可以避免大量与 NULL 相关的问题。

于 2008-09-12T17:00:52.770 回答
3

如果将来这些一对一关系中的任何一个可能变为一对多或多对多,那么多表数据库会更加灵活。例如,如果您需要为某些客户存储多个地址,如果您有一个客户表和一个地址表,这会容易得多。我真的看不到您可能需要复制地址的某些部分而不是其他部分的情况,因此单独的地址、城市、州和邮政编码表可能有点过分。

于 2008-09-12T16:50:00.517 回答
3

像其他一切一样:这取决于。

关于列数与表数没有硬性规定。

如果您的客户需要拥有多个地址,那么单独的表格是有意义的。如果您有充分的理由将 City 列标准化为自己的表,那么也可以这样做,但我以前从未见过,因为它是一个自由格式的字段(通常)。

桌子很重,标准化的设计在空间方面是有效的,看起来“教科书式”,但可能会变得非常复杂。它看起来不错,直到您必须执行 12 次连接才能获得客户的姓名和地址。就最重要的性能而言,这些设计并不自动出色:查询。

尽可能避免复杂性。例如,如果客户只能有两个地址(不是任意多个),那么将它们全部保存在一个表中(CustomerID、Name、ShipToAddress、BillingAddress、ShipToCity、BillingCity 等)可能是有意义的。

这是 Jeff关于该主题的帖子。

于 2008-09-12T16:53:43.237 回答
2

拥有较少列的表有很多好处,但您还需要查看上面的场景并回答以下问题:

是否允许客户拥有超过 1 个地址?如果不是,则不需要单独的地址表。如果是这样,那么单独的表格会很有帮助,因为您可以根据需要轻松添加更多地址,而在表格中添加更多列变得更加困难。

于 2008-09-12T16:48:49.520 回答
1

我会考虑将标准化作为第一步,因此城市、县、州、国家/地区最好作为单独的列... SQL 语言的强大功能以及今天的 DBMS-es 允许您稍后在需要查看时对数据进行分组它在其他一些非标准化视图中。

在开发系统时,如果您认为这是一种改进,您可能会考虑“非规范化”某些部分。

于 2008-09-12T16:48:25.090 回答
1

在这种情况下,我认为平衡是有序的。如果将列放入表中有意义,则将其放入表中,如果没有,则不要。您的同事的方法肯定有助于规范化数据库,但如果您必须将 50 个表连接在一起以获得所需的信息,这可能不是很有用。

我想我的答案是,用你最好的判断。

于 2008-09-12T16:48:35.963 回答
1

这有很多方面,但从应用程序效率的角度来看,mote 表有时可能更有效。如果每次数据库执行操作时都有几个带有一堆列的表,它就有机会锁定,那么在锁定期间会有更多数据不可用。如果锁升级到页面和表(希望不是表:)),您可以看到这会如何降低系统速度。

于 2008-09-12T16:49:44.870 回答
1

唔。

我认为它是一种洗涤,取决于您的特定设计模型。绝对将具有多个字段的实体分解到自己的表中,或者实体的构成可能会随着应用程序需求的变化而变化(例如 - 我无论如何都会排除地址,因为它有很多字段,但我如果您认为有任何机会需要处理外国地址(可以是不同的形式。电话号码也一样),您会特别这样做。

也就是说,当你让它工作时,请注意性能。如果您将一个实体拆分出来,需要您进行大型、昂贵的联接,那么将该表拆分回原始表可能会成为更好的设计决策。

于 2008-09-12T17:46:46.310 回答
1

当您设计数据库时,您应该尽可能接近数据的含义,而不是您的应用程序需要!

一个好的数据库设计应该可以保持 20 多年不变。

一个客户可能有多个地址,这就是现实。如果您决定将您的应用程序限制为第一个版本的一个地址,那么它关注的是您的应用程序的设计而不是数据!

如果您想简化查询,最好有多个表而不是多个列并使用视图。

大多数情况下,数据库的性能问题与网络性能(单行结果的链式查询、获取不需要的列等)有关,而不是与查询的复杂性有关。

于 2014-07-29T07:46:36.360 回答
0

使用尽可能少的列进行查询有很大的好处。但是表本身可以有很大的数字。杰夫也谈到了这一点。

基本上,确保在进行查询时要求的内容不会超过您的需要 - 查询的性能与您要求的列数直接相关。

于 2008-09-12T16:49:50.563 回答
0

我认为您必须先查看您存储的数据类型,然后再做出决定。拥有地址表很好,但前提是多个人共享同一地址的可能性很高。如果每个人都有不同的地址,那么将这些数据保存在不同的表中只会引入不必要的连接。

我看不到拥有城市表的好处,除非城市本身就是您在应用程序中关心的实体。或者,如果您想限制用户可用的城市数量。

底线是这样的决定必须在开始提高效率之前考虑应用程序本身。国际海事组织。

于 2008-09-12T16:50:04.930 回答
0

首先,规范化您的表格。这可以确保您避免冗余数据,从而减少要扫描的数据行,从而改进您的查询。然后,如果您遇到要连接的规范化表导致查询需要很长时间来处理(昂贵的连接子句)的点,请在更合适的地方进行非规范化。

于 2014-08-11T21:01:02.617 回答
0

很高兴看到这么多鼓舞人心且基础良好的答案。

我的回答是(不幸的是):这取决于。

两种情况: * 如果您创建一个要使用多年的数据模型,因此可能必须适应许多未来的变化:使用更多的表和更少的行以及非常严格的规范化。* 在其他情况下,您可以在多表少行或少表多行之间进行选择。特别是对于这个主题相对较新的人来说,最后一种方法可能更直观,更容易理解。

The same is valid for the choosing between the object oriented approach and other options.

于 2016-11-21T12:11:41.617 回答