MySQL:多个表还是一个包含许多列的表?


124

因此,这更多是一个设计问题。

我有一个主键(例如用户的ID),并且有大量与该用户相关联的信息。

我应该根据信息将多个表细分为几类,还是只有一个表包含许多列?

我过去这样做的方法是有多个表,例如,一个表用于应用程序使用情况数据,一个表用于配置文件信息,一个表用于后端令牌,等等,以使事情看起来井井有条。

最近有人告诉我,最好不要那样做,有一个包含很多列的表也可以。关键是,所有这些列都具有相同的主键。

我是数据库设计的新手,所以哪种方法更好,优缺点是什么?

常规的做法是什么?


为了清楚起见,如果我错了,请指正我,但我认为“多个表”可以理解为链接/关联表: en.wikipedia.org/wiki/Associative_entity
cellepo

1
该数据库是否需要用于分析目的或用于操作/事务处理?
亚历山大·拉德夫

Answers:


112

任何时候信息都是一对一的(每个用户都有一个用户名和密码),那么最好在一个表中使用它,因为它减少了数据库检索结果所需的联接数。我认为某些数据库对每个表的列数有限制,但是在正常情况下我不会担心它,如果需要的话,以后可以随时拆分它。

如果数据是一对多的(每个用户有成千上万的使用信息行),则应将其拆分为单独的表以减少重复的数据(重复的数据会浪费存储空间,缓存空间,并使数据库难以维护)。

您可能会发现有关数据库规范化的Wikipedia文章很有趣,因为它深入讨论了这样做的原因:

数据库规范化是组织关系数据库的字段和表以最小化冗余和依赖性的过程。规范化通常涉及将大表划分为较小(和较少冗余)的表,并定义它们之间的关系。目的是隔离数据,以便可以仅在一个表中进行字段的添加,删除和修改,然后通过定义的关系传播到数据库的其余部分。

还需要注意非规范化,因为在某些情况下重复数据会更好(因为它减少了数据库读取数据时需要做的工作量)。我强烈建议您尽可能使数据规范化,以开始使用,并且仅当您知道特定查询中的性能问题时才进行规范化。


感谢您的回答,因此在阅读后,我认为我所说的是一对一的信息情况,即用户有许多一对一的列。
Xavier_Ex 2012年

@Xavier_Ex-是的,如果每个用户只有一列,那么只有一个巨大的用户表将更易于使用(并且数据库引擎优化起来也容易得多)。
布伦丹·朗

您编辑的帖子提供了更多有用的信息!我有一个新的担忧,如果某些列会经常更新,是否应该将它们放在单独的表中?例如,用户的出生日期将永远不会更新,但是后端令牌可能会在一段时间后失效,并且需要频繁更新。如果以这种方式分离表以提高性能会更好吗?我现在将阅读您提到的Wiki :)
Xavier_Ex 2012年

@Xavier_Ex-我不推荐它。当您可以在一张表中查找所需的所有数据时,您将获得明显更好的性能(请参阅非规范化文章)。联接很昂贵,因为(1)它们需要在多个位置查找数据,这可能涉及在旋转磁盘上进行查找;(2)通常需要多个索引和某种类型的合并;(3)它们使查询计划变得更加困难,而这并没有不仅要花时间,而且还会增加查询优化器出错的机会(而优化不佳的查询可能真的很慢)。
布伦丹·朗

1
最近,我遇到了同样的问题,因为MySQL InnoDB表的长度限制相对较小(〜8000字节)。在我的问题表(非常长的保险单中的数据,超过100列)中,我们有多个varchar列,均为UTF8。因此,我们轻松地填充了约8000个字节的限制,并始终收到“来自存储引擎的错误139”。因此,我们不得不拆分表。(我们使用了新的梭子鱼格式进行了测试,该格式无需拆分即可工作,但客户端的服务器仍使用MySQL 5.0)。
MV。

12

一个大桌子通常是一个糟糕的选择。相关表是设计用于关系数据库的对象。如果您正确地建立索引并且知道如何编写性能查询,它们将表现良好。

当表中的列过多时,您可能会遇到数据库在其上存储信息的页面实际大小的问题。记录可能最终对于页面而言太大,从而可能导致您最终无法创建或更新使用户不满意的特定记录,或者您(至少在SQL Server中)可能因某些原因而溢出数据类型(如果要执行此操作,则需要查找一组规则),但是如果许多记录将使页面大小溢出,则会造成严重的性能问题。现在,MYSQL如何处理页面以及潜在页面大小过大时是否有问题,您需要在该数据库的文档中查找。


1
声音不同啊!总是很棒。感谢您的信息!我会确保在摆桌子时会意识到这一点...但是我不知道我本来必须知道这么低级的东西。
Xavier_Ex 2012年

4

我有一个很好的例子。具有以下一组关系的过度标准化的数据库:

people -> rel_p2staff -> staff

people -> rel_p2prosp -> prospects

在人员具有姓名和人员详细信息的地方,人员仅具有人员记录的详细信息,潜在客户仅具有潜在客户的详细信息,而rel表是关系表,其中包含来自与人员和潜在人员链接的人员的外键。

这种设计针对整个数据库进行。

现在要查询这组关系,每次都是一个多表联接,有时是8个或更多的表联接。到今年年中,它的运行情况一直很好,当时它开始变得非常缓慢,现在我们已经超过了40000条记录。

索引和所有低落的成果已于去年用完,所有查询都经过优化以达到完美。这是特定规范化设计的道路的尽头,现在,管理人员已批准在6个月内对依赖于该应用程序的整个应用程序进行重新构建以及数据库的重组。$$$$哎呀。

解决方案将是people -> staffpeople -> prospect


有兴趣知道重建如何进行吗?您是否最终设计出了与type存在a staff或a的单表继承类似的东西prospect
Coderama

1
与直系人脉->员工与人脉->前景,作品魅力十足,易于使用,查询迅速。
Vlad17年

4

遇到了这个问题,并且作为一个经常使用MySQL的人,然后最近又切换到Postgres,最大的优势之一就是可以将JSON对象添加到Postgres中的字段。

因此,如果您处在这种情况下,则不必在一个包含很多列的大表之间做出决定并进行拆分,但是您可以将列合并到JSON对象中以减少它,例如,而不是将地址分配为5列,成为一个。您也可以查询该对象。


查询时使用json对象时的性能如何?
dagalti

1
@dagalti对于我使用过的应用程序来说性能很好。我尚未对其进行基准测试,但这可能对您有用
moinhaque

3

如果将所有内容放在一个表中,会问自己这些问题,该用户是否会有多行?如果必须更新用户,是否要保留审核记录?用户可以拥有一个数据元素的多个实例吗?(例如电话号码),您是否可能想在以后添加一个元素或一组元素?如果回答是,则很可能希望具有带有外键关系的子表。

父/子表的优点是数据完整性,通过索引的性能(是的,您也可以在平面表上完成)以及如果以后需要添加字段(尤其是必填字段)时,IMO易于维护。

缺点设计更难,查询变得稍微复杂

但是,在很多情况下,一个大的平板将是合适的,因此您必须根据自己的情况来决定。


谢谢你提醒我!因此,在我的情况下,我仅考虑每个用户不能有多于一行的情况,因此所有信息字段都是一对一的。同样,用户不能拥有同一元素的一个以上实例,因为我相信一个元素的概念不能存在于一个以上的位置。对于第三个问题,是的,我可以在表中添加更多元素,但是它们不会破坏我上面提到的要求。我想将多个行关联到一个用户时,父/子表很好,但是在这种情况下,我担心的是一个用户有许多一对一的列。
Xavier_Ex 2012年

即使当前所有元素都是一一对应的,也不能排除使用IMO的父/子表的必要性。记录更改的数据是一种用途。延迟加载对象是另一个。虽然单个表结构有好处,但父子布局也有好处(尽管我也看到人们对这些东西也走极端了)。
Brian

1

我已经完成了某种数据库设计。对我来说,这取决于数据库管理系统的难度。是的,仅在一个地方拥有唯一的数据是正确的,但是使用具有大量记录的过规范化数据库进行查询确实非常困难。只需结合两个架构即可;如果您觉得自己将拥有海量的记录,而这些记录难以维护,例如facebook,gmail等,则使用一张大表。并为简单的系统使用一组不同的表来记录...好吧,这只是我的意见..我希望它可以对您有所帮助..您可以做到... :)


1
“如果您要拥有大量记录,请使用一个巨大的表。”但是Facebook,Google不会将用户数据存储在一个表中,而是将用户数据分成多个表。
亚米·奥德梅尔

0

这样做的常规方法是使用不同的表,如星型模式或雪花模式。豪威尔,我将这种策略定为两个方面。我相信从理论上讲,数据应该只存在于一个地方,因为我提到的模式可以很好地工作。但是,我还认为,对于报表引擎和BI套件,采用列式方法将带来极大的好处,因为它可以更好地支持报表需求。像infobright.org这样的柱状方法具有巨大的性能提升和压缩效果,这使得使用这两种方法都非常有用。许多公司开始意识到组织中只有一种数据库体系结构并不能满足其全部需求。许多公司正在同时实现具有多个数据库体系结构的概念。


感谢您提供的信息,但是对不起,我不太了解您的回答...我将对您首先提到的两个模式进行搜索...
Xavier_Ex 2012年

-4

我认为拥有单个表会更有效,但是您应该确保表的组织方式能够显示出关系,趋势以及同一行变量之间的差异。例如,如果表格显示了学生的年龄和年级,则您应该以一种方式排列表格:感谢得分最高的人与得分最低的人可以很好地区分,并且学生年龄的差异是均匀的。

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.