【问题标题】:MySQL: multiple tables or one table with many columns?MySQL:多张表还是一张多列的表?
【发布时间】:2012-04-04 04:57:34
【问题描述】:

所以这更像是一个设计问题。

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

我应该根据信息将多张表格分为几类,还是应该只有一张多列的表格?

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

最近有人告诉我,最好不要那样做,而且有一张有很多列的表就可以了。问题是,所有这些列都有相同的主键。

我对数据库设计很陌生,那么哪种方法更好,优缺点是什么?

传统的做法是什么?

【问题讨论】:

  • 为清楚起见,如果我错了,请纠正我,但我认为“多表”可以理解为链接/关联表:en.wikipedia.org/wiki/Associative_entity
  • 此数据库是否需要用于分析目的或用于操作/事务处理?

标签: mysql database-design


【解决方案1】:

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

如果数据是一对多的(每个用户有上千行的使用信息),那么应该拆分成单独的表来减少重复数据(重复数据浪费存储空间、缓存空间,并使数据库更难维护)。

您可能会发现 database normalization 上的 Wikipedia 文章很有趣,因为它深入讨论了其中的原因:

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

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

【讨论】:

  • 感谢您的回答,所以看完之后我想我说的是一对一的信息情况,当用户有很多一对一的列时。
  • @Xavier_Ex - 是的,如果每个用户只有一列,那么只有一个巨大的用户表将更容易使用(并且数据库引擎更容易优化)。
  • 您编辑的帖子提供了更多有用的信息!我有一个新的担忧,如果某些列会经常更新,我应该将它们放在单独的表中吗?例如,用户的出生日期永远不会更新,但后端令牌可能会在一段时间后失效,并且需要频繁更新。如果我以这种方式分隔表以提高性能会更好吗?我现在将阅读您提到的 wiki :)
  • @Xavier_Ex - 我不会推荐它。当您可以在一个表中查找所需的所有数据时,您将获得明显更好的性能(请参阅非规范化文章)。连接很昂贵,因为 (1) 它们需要在多个位置查找数据,这可能涉及在旋转磁盘上查找,(2) 通常需要多个索引和某种合并,以及 (3) 它们使查询计划变得更加困难,这不是只需要时间,但也会增加查询优化器出错的可能性(而且优化不佳的查询可能真的很慢)。
  • 最近我也遇到了同样的问题,因为 MySQL InnoDB 表的长度限制相对较小(~8000 字节)。在我的问题表(来自非常冗长的保险表格的数据,超过 100 列)中,我们有多个 varchar 列,都是 UTF8。因此,我们轻松地填充了约 8000 字节的限制,并且一直收到“来自存储引擎的错误 139”。所以我们不得不拆分桌子。 (我们使用较新的梭子鱼格式进行了测试,它没有拆分,但我们客户的服务器仍然使用 MySQL 5.0)。
【解决方案2】:

一张大桌子通常是一个糟糕的选择。相关表是关系数据库的设计目的。如果您正确索引并知道如何编写高性能查询,那么它们将执行得很好。

当表获得太多列时,您可能会遇到数据库存储信息的页面的实际大小问题。记录可能最终对于页面来说太大了,您可能最终无法创建或更新使用户不满意的特定记录,或者您可能(至少在 SQL Server 中)被允许某些特定的溢出数据类型(如果您这样做,您需要查找一组规则)但是如果许多记录会溢出页面大小,您可能会产生巨大的性能问题。现在 MYSQL 如何处理页面以及当潜在页面大小变得太大时是否有问题是您必须在该数据库的文档中查找的内容。

【讨论】:

  • 啊不同的声音!这总是很棒。感谢您的信息!我会确保我在制作表格时意识到这一点......但我不知道我最初必须意识到这些低级的东西。
【解决方案3】:

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

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

【讨论】:

  • 查询时使用json对象的性能如何?
  • @dagalti 对于我使用过的应用程序来说,性能很好。我还没有对它进行自己的基准测试,但这可能对你有用:arangodb.com/2018/02/…
【解决方案4】:

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

people -> rel_p2staff -> staff

people -> rel_p2prosp -> prospects

人们有姓名和个人详细信息,员工只有员工记录详细信息,潜在客户只有潜在客户详细信息,而 rel 表是关系表,其中包含来自链接到员工和潜在客户的人员的外键。

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

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

索引和所有低挂的果实去年都用完了,所有查询都优化到完美。这是特定规范化设计和管理的终点,现在批准重建依赖于它的整个应用程序以及重组数据库,为期 6 个月。 $$$$ 哎哟。

解决方案是与people -> staffpeople -> prospect 建立直接关系

【讨论】:

  • 有兴趣了解重建的过程吗?您是否最终设计了类似于单表继承的东西,其中 typestaffprospect
  • 与直接关系人员 -> 员工和人员 -> 潜在客户,工作魅力,易于使用,快速查询。
【解决方案5】:

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

父/子表的优点是数据完整性、通过索引提高性能(是的,您也可以在平面表上执行此操作)以及如果您稍后需要添加字段,特别是如果它是必填字段,则 IMO 更易于维护.

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

但是,在很多情况下,一张大平桌是合适的,所以你必须看你的情况来决定。

【讨论】:

  • 谢谢你的提醒!所以在我的情况下,我只考虑每个用户不能超过一行的情况,因此所有信息字段都是一对一的。此外,用户不能拥有多个相同元素的实例,因为我相信一个元素不能存在于多个地方的概念。对于第三个问题,是的,我可能会在表格中添加更多元素,但它们不会破坏我上面提到的要求。当我想将多行关联到一个用户时,我认为父/子表很好,但在这种情况下,我担心的是用户有很多一对一的列。
  • 即使所有元素当前都是一对一的,但这并不能消除拥有父/子表 IMO 的需要或愿望。保留更改数据的日志是一种用途。延迟加载对象是另一个。虽然单个表结构有好处,但父子布局也有好处(尽管我也看到人们在这些方面走极端)。
【解决方案6】:

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

【讨论】:

  • “如果您将拥有大量记录,请使用一个巨大的表。”但是 Facebook、Google 不会将用户数据存储在单个表中,而是将它们分隔为多个表。跨度>
【解决方案7】:

执行此操作的传统方法是使用不同的表,如星形模式或雪花模式。 Howeevr,我认为这个策略是双重的。我相信数据应该只存在于一个地方的理论,在那里我提到的模式会很好地工作。但是,我也相信对于报告引擎和 BI 套件,柱状方法将非常有益,因为它更支持报告需求。像 infobright.org 这样的列式方法具有巨大的性能提升和压缩,这使得使用这两种方法非常有用。许多公司开始意识到,组织中只有一种数据库架构并不能满足他们的全部需求。许多公司都在实施拥有多个数据库架构的概念。

【讨论】:

  • 感谢您提供信息,但很抱歉我不太明白您的回答...我将搜索您首先提到的两个架构...
【解决方案8】:

我认为使用单个表格更有效,但您应该确保表格的组织方式能够显示关系、趋势以及同一行变量的差异。 例如,如果表格显示了学生的年龄和成绩,您应该以一种方式排列表格,感谢最高得分者与最低得分者有很好的区别,并且学生的年龄差异是均匀的。

【讨论】:

  • 我看不出你来自哪里。
猜你喜欢
  • 2012-11-28
  • 2011-06-20
  • 2020-03-25
  • 1970-01-01
  • 2014-01-31
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
相关资源
最近更新 更多