有什么更好的数据库设计:更多表或更多列?


77

一位前同事坚持认为,一个数据库的表更多,每个表的列更少,比一个数据库的表较少,每个表的列数更多。例如,您将没有名称表,地址表,城市表等,而不是具有名称,地址,城市,州,邮政编码等列的客户表。

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

因此,具有较少列的更多表相对于具有较多列的较少表有什么明显的好处吗?

Answers:


59

设计数据库时,我遵循一些非常简单的经验法则,我认为这些规则可用于帮助做出这样的决策...。

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

这些规则的通常结果是,初始设计将偏爱表而不是列,重点是消除冗余。随着项目的进展和非规范化点的确定,总体结构将朝着平衡的方向发展,以有限的冗余和色谱柱扩散为代价,以换取其他有价值的利益。


什么是“下游表格”?
橄榄色

1
我的意思是“数据流”上下文中的“下游”。从本质上讲,这意味着您具有一个使用规范化表作为源并以某种方式转换数据,然后将结果存储到其他位置的过程。
克里斯·阿默曼

12

我会主张使用更多的表,但只能使用到一定程度。以您的示例为例,如果将用户信息分成两个表(例如:USERS和ADDRESS),则可以灵活地为每个用户提供多个地址。一个明显的应用是拥有单独账单和送货地址的用户。

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


11

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

Jeff就StackOverflow的设计了一些有关它的内容。另请参阅Jeff链接到Dare Obasanjo的文章


1
根据我的经验,这显然是错误的。我已经处理了连接数十个表的查询,每个表包含100万以上的行,而且只要您要连接主键,结果就会很快返回。
JosephStyons 08/09/12

1
什么是“快速”?如果您正在运行一个网站,试图以每秒第二次“足够快”的速度提供数千个网页浏览,这与单一用户数据库的含义完全不同,后者您所关心的只是用户的响应时间。
克里斯·厄普彻奇

“只要您使用主键,结果就会很快返回。”好吧,是的。但是,我有更多的经验表,越有可能是加入非PK的,非索引列等情况发生
swilliams

规范化和表的后续连接通常有助于提高性能,因为根据定义,您可以更具选择性,并避免使用表扫描(这是最慢的选择方法)。
Ed Guiness

设计不良通常是导致性能不佳而不是标准化的最大因素。
Ed Guiness

5

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

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

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


同意 我只进行过规范化以降低查询复杂性,通常是为了消除与ORM的某些阻抗不匹配。从来没有,即使是大规模的性能优化也是必需的。
本·西蒙斯

5

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


4

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

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


3

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


我有40个关于用户信息的唯一字段,这些字段是唯一的,它们是User Authentication System中的一对一字段。如果我将40列保留在一张表中,您认为可以吗?如果我将它们分开,则需要在查询中写更多的联接:-(.。您能建议
vkrams 2013年

3

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

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

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

表格繁重,规范化的设计在空间方面非常有效,看起来“教科书不错”,但会变得极其复杂。除非您必须进行12次联接才能获得客户的姓名和地址,否则它看起来不错。就最重要的性能而言,这些设计并非自动出色:查询。

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

这是杰夫关于该主题的帖子


2

具有较少列的表有很多优点,但是您还需要查看上面的情况并回答以下问题:

允许客户使用多个地址吗?如果不是,则不需要单独的地址表。如果是这样,那么一个单独的表将很有用,因为您可以轻松地根据需要添加更多地址,而在该表中添加更多列将变得更加困难。


1

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

在开发系统时,如果您认为这是一项改进,则可以考虑“标准化”某些部分。


1
我的2美分:我必须不同意;在设计过程中进行这种优化是过早优化的经典案例。等到您发现性能问题再牺牲一个好的设计。
JosephStyons

1

我认为在这种情况下要保持平衡。如果在表中放置一列是有意义的,则将其放在表中,如果没有,则不要。您的同事方法一定会帮助标准化数据库,但是如果您必须将50个表连接在一起以获取所需的信息,那可能就没有太大用处。

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


1

这有很多方面,但是从应用程序效率的角度来看,表有时会更高效。如果每次db进行操作时,如果有几个表具有一堆列,则有机会进行锁定,则在锁定期间将使更多数据不可用。如果锁升级到页面和表(最好不是表:)),您将看到它如何降低系统速度。


1

我认为这很麻烦,取决于您的特定设计模型。一定要在其自己的表中排除具有多个字段的实体,或者其组成可能会随您的应用程序需求的变化而更改的实体(例如-我还是要排除地址,因为它有很多字段,但是我倒是特别做,如果你认为有没有机会你需要处理国外的地址,可以是不同的形式,与电话号码相同)。

就是说,当您开始工作时,请密切注意性能。如果您将一个实体分解出来,需要进行大型,昂贵的连接,那么将该表旋转回原始表可能是一个更好的设计决策。


1

在设计数据库时,应该尽可能地远离数据的含义,而不是应用程序所需要的!

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

一个客户可能有多个地址,这就是事实。如果您决定在第一个发行版中您的应用程序被限制为一个地址,则与应用程序的设计有关,而不是数据!

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

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


0

使用尽可能少的列进行查询有很大的好处。但是表本身可以有很多。杰夫对此也说了些话。

基本上,请确保您查询的内容不超过所需数量,查询的性能与所需的列数直接相关。


0

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

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

最重要的是,这样的决定必须在开始提高效率之前考虑应用程序本身。海事组织。


0

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


0

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

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

两种情况:*如果您创建了一个将要使用多年的数据模型,因此可能不得不适应许多将来的更改:请使用更多的表,更少的行以及相当严格的规范化。*在其他情况下,您可以在更多表少行或更少表多行之间进行选择。特别是对于刚接触该主题的人们,后一种方法可以更直观,更容易理解。

对于面向对象方法和其他选项之间的选择,这同样有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.