120

我将各种用户详细信息存储在我的 MySQL 数据库中。最初它是在各种表中设置的,这意味着数据与 UserIds 相关联,并通过有时复杂的调用输出以根据需要显示和操作数据。建立一个新系统,将所有这些表格组合成一个相关内容的大表格几乎是有意义的。

  • 这会是帮助还是阻碍?
  • 调用、更新或搜索/操作时的速度考虑?

这是我的一些表结构的示例:

  • users - UserId、用户名、电子邮件、加密密码、注册日期、ip
  • user_details - cookie 数据、姓名、地址、联系方式、隶属关系、人口统计数据
  • user_activity - 投稿、上次在线、上次查看
  • user_settings - 个人资料显示设置
  • user_interests - 广告目标变量
  • user_levels - 访问权限
  • user_stats - 命中、统计

编辑:到目前为止,我已经对所有答案投了赞成票,它们都具有基本上回答我的问题的元素。

大多数表具有 1:1 的关系,这是对它们进行非规范化的主要原因。

如果表格跨越 100 多列,而这些单元格中的大部分可能保持为空,是否会出现问题?

4

8 回答 8

74

多个表在以下方式/情况下有帮助:

(a) 如果不同的人要开发涉及不同表的应用程序,那么拆分它们是有意义的。

(b) 如果你想在数据收集的不同部分给不同的人不同的权限,拆分它们可能更方便。(当然,您可以查看定义视图并适当地对其进行授权)。

(c) 为了将数据移动到不同的地方,尤其是在开发过程中,使用导致文件更小的表格可能是有意义的。

(d) 当您开发针对单个实体的特定数据收集的应用程序时,较小的占地面积可能会给您带来舒适感。

(e) 有一种可能性:您认为的单值数据将来可能会变成真正的多值。例如,到目前为止,信用额度是一个单值字段。但是明天,您可能决定将值更改为(日期从、日期到、信用值)。拆分表现在可能会派上用场。

我的投票将支持多个表 - 数据适当拆分。

祝你好运。

于 2009-07-14T12:46:33.447 回答
39

组合这些表称为非规范化。

它可能(或可能不会)有助于使一些查询(产生大量JOINs)以创建维护地狱为代价更快地运行。

MySQL能够使用唯一的JOIN方法,即NESTED LOOPS

这意味着对于驱动表中的每条记录,MySQL在循环中定位驱动表中的匹配记录。

定位记录是一项相当昂贵的操作,可能需要几十倍于纯记录扫描的时间。

将所有记录移到一张表中可以帮助您摆脱这种操作,但表本身会变大,并且表扫描需要更长的时间。

如果您在其他表中有很多记录,那么增加表扫描可能会超过按顺序扫描记录的好处。

另一方面,维护地狱是有保证的。

于 2009-07-14T12:21:50.037 回答
18

他们都是1:1的关系吗?我的意思是,如果一个用户可能属于不同的用户级别,或者如果用户兴趣在用户兴趣表中表示为几条记录,那么立即合并这些表将是不可能的。

关于之前关于规范化的回答,不得不说数据库规范化规则完全不顾性能,只看什么是整洁的数据库设计。这通常是您想要实现的目标,但有时主动非规范化以追求性能是有意义的。

总而言之,我想说问题归结为表中有多少字段,以及它们被访问的频率。如果用户活动通常不是很有趣,那么出于性能和维护的原因,总是将它放在同一个记录上可能只是一件麻烦事。如果某些数据(例如设置)经常被访问,但只是包含太多字段,则合并表也可能不方便。如果您只对性能提升感兴趣,您可能会考虑其他方法,例如将设置分开,但将它们保存在它们自己的会话变量中,这样您就不必经常查询数据库以获得它们。

于 2009-07-14T12:27:59.277 回答
16

所有这些表都有1-to-1关系吗?例如,每个用户行在user_statsor中是否只有一个对应的行user_levels?如果是这样,将它们组合到一个表中可能是有意义的。如果关系不是 1 to 1,那么将它们组合(非规范化)可能没有意义。

将它们放在单独的表中而不是在一张表中可能对性能影响不大,除非您拥有数十万或数百万条用户记录。您将获得的唯一真正收获是通过组合查询来简化查询。

预计到达时间:

如果您担心太多,那么请考虑一下您通常一起使用哪些东西并将它们组合起来,将其余部分留在一个单独的表中(或者如果需要,可以使用几个单独的表)。

如果您查看使用数据的方式,我猜您会发现 80% 的查询使用了 20% 的数据,而其余 80% 的数据只是偶尔使用。将经常使用的 20% 合并到一张表中,将不经常使用的 80% 留在单独的表中,您可能会有一个很好的折衷方案。

于 2009-07-14T12:25:17.840 回答
9

创建一个庞大的表违背了关系数据库的原则。我不会将它们全部合并到一张表中。您将获得重复数据的多个实例。例如,如果您的用户有三个兴趣,您将有 3 行,其中包含相同的用户数据只是为了存储三个不同的兴趣。肯定会选择多重“标准化”表方法。有关数据库规范化,请参阅Wiki 页面。

编辑: 我已经更新了我的答案,因为你已经更新了你的问题......我现在更同意我最初的回答......

这些单元格中的很大一部分可能会保持空白

例如,如果用户没有任何兴趣,那么如果您进行规范化,那么您将不会在该用户的兴趣表中出现一行。如果您将所有内容都放在一张大表中,那么您将拥有仅包含 NULL 的列(并且显然很多列)。

我曾在一家电话公司工作,那里有大量表格,获取数据可能需要多次连接。当从这些表中读取的性能至关重要时,创建的过程可以生成一个平面表(即非规范化表),该表不需要报告可能指向的连接、计算等。然后将这些与 SQL 服务器代理结合使用以在特定时间间隔运行作业(即,某些统计数据的每周视图将每周运行一次,依此类推)。

于 2009-07-14T12:22:24.453 回答
7

为什么不使用与 Wordpress 相同的方法,即拥有一个包含每个人都拥有的基本用户信息的用户表,然后添加一个“user_meta”表,该表基本上可以是与用户 ID 关联的任何键、值对。因此,如果您需要查找用户的所有元信息,您可以将其添加到您的查询中。如果不需要登录等操作,您也不必总是添加额外的查询。这种方法的好处还使您的表可以为您的用户添加新功能,例如存储他们的 twitter 句柄或每个个人兴趣。您也不必处理关联 ID 的迷宫,因为您有一个管理所有元数据的表,并且您将其限制为只有一个关联而不是 50 个。

Wordpress 专门这样做是为了允许通过插件添加功能,因此允许您的项目更具可扩展性,并且如果您需要添加新功能,则不需要完整的数据库检修。

于 2013-05-07T14:46:50.250 回答
5

我认为这是“视情况而定”的情况之一。拥有多个表更干净,理论上可能更好。但是当您必须连接 6-7 个表来获取有关单个用户的信息时,您可能会开始重新考虑这种方法。

于 2009-07-14T12:24:21.943 回答
1

我会说这取决于其他表的真正含义。一个 user_details 是否包含超过 1 个 / 用户等等。什么级别的标准化最适合您的需求取决于您的需求。

如果您有一张具有良好索引的表,那可能会更快。但另一方面可能更难维护。

在我看来,您可以跳过 User_Details,因为它可能与用户是一对一的关系。但其余的可能每个用户有很多行?

于 2009-07-14T12:27:18.323 回答