多个 MySQL 表还是一个大表,哪个更有效?

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

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

下面是我的一些表结构的例子:

  • User-UserId,username,email,加密密码,注册日期,ip
  • User _ Details-cookie 数据、姓名、地址、联系方式、联系方式、人口统计数据
  • User _ activity ——贡献,最后一次在线,最后一次查看
  • User _ sets-配置文件显示设置
  • User _ interest-广告目标变量
  • User _ level-访问权限
  • User _ stats-hit,tallies

编辑: 到目前为止,我已经对所有的答案进行了投票,它们都有一些基本上可以回答我的问题的元素。

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

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

93620 次浏览

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

它可能(也可能不)有助于进行一些查询(这些查询产生了大量的 JOINs) ,以创建一个维护地狱为代价来提高运行速度。

MySQL只能使用 JOIN方法,即 NESTED LOOPS

This means that for each record in the driving table, MySQL locates a matching record in the driven table in a loop.

定位一个记录是一个相当昂贵的操作,其耗时可能是纯记录扫描的几十倍。

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

如果在其他表中有大量记录,那么表扫描的增加可能会超出顺序扫描记录的好处。

Maintenance hell, on the other hand, is guaranteed.

创建一个巨大的表格违背了关系数据库的原则。我不会把它们放在一张桌子上。您将获得多个重复数据实例。例如,如果您的用户有三个兴趣,那么您将有3行,其中包含相同的用户数据,以存储三个不同的兴趣。明确地采用多个“规范化”表的方法。有关数据库规范化,请参阅 这个 Wiki 页面。

编辑: 我已经更新了我的答案,就像你更新了你的问题一样... ... 我现在更加同意我最初的答案,因为... ..。

这些细胞的大部分是 可能仍然是空的

If for example, a user didn't have any interests, if you normalize then you simple wont have a row in the interest table for that user. If you have everything in one massive table, then you will have columns (and apparently a lot of them) that contain just NULL's.

我曾在一家电话公司工作,那里有成吨的表,获取数据可能需要许多连接。当从这些表中读取的性能非常关键时,创建的过程可以生成一个平面表(即非规范化表) ,不需要报告指向的连接、计算等。然后与 SQL 服务器代理一起使用它们,以特定的间隔运行作业(例如,每周查看一次某些统计数据,以此类推)。

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

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

Having them in separate tables vs. one table is probably going to have little effect on performance though unless you have hundreds of thousands or millions of user records. The only real gain you'll get is from simplifying your queries by combining them.

预计到达时间:

如果您的 关心是关于 柱子太多了的,那么考虑一下 what stuff you typically use together and combine those,将其余的留在一个单独的表中(或者如果需要的话,留在几个单独的表中)。

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

我会说这取决于其他桌子的真正含义。 User _ Details 是否包含多于1个/users 等等。 什么级别的规范化最适合您的需求取决于您的需求。

如果您有一个具有良好索引的表,那么速度可能会更快。但另一方面可能更难维持。

对我来说,它看起来像你可以跳过用户详细信息,因为它可能是1对1的关系与用户。 But the rest are probably alot of rows per user?

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

关于以前关于规范化的回答,必须指出的是,数据库规范化规则完全忽视了性能,只是在考虑一个整洁的数据库设计。这通常是您想要实现的目标,但是有时候在追求性能的过程中积极地去规范化是有意义的。

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

多个表格有助于以下方面/情况:

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

(b)如果你希望就不同的资料收集部分给予不同的人不同的权限,分开处理这些权限可能会更方便。(当然,您可以查看定义视图并对其进行适当授权)。

(c)为了将数据移动到不同的地方,特别是在开发期间,使用导致文件大小较小的表可能是有意义的。

(d)在开发单个实体的特定数据收集应用程序时,较小的脚印可能会带来舒适感。

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

我的选择是多个表格-数据适当分割。

祝你好运。

Why not use the same approach Wordpress does by having a users table with basic user information that everyone has and then adding a "user_meta" table that can basically be any key, value pair associated with the user id. So if you need to find all the meta information for the user you could just add that to your query. You would also not always have to add the extra query if not needed for things like logging in. The benefit to this approach also leaves your table open to adding new features to your users such as storing their twitter handle or each individual interest. You also won't have to deal with a maze of associated ID's because you have one table that rules all metadata and you will limit it to only one association instead of 50.

Wordpress specifically does this to allow for features to be added via plugins, therefore allowing for your project to be more scalable and will not require a complete database overhaul if you need to add a new feature.

大型表的性能考虑

“ Like”和“ views” (etc)是性能1:1关系的极少数有效案例之一。这可以防止非常频繁的 UPDATE ... +1干扰其他活动,反之亦然。
底线: 在非常大和繁忙的表中分离频繁计数器。

另一种可能的情况是,您有一组 很少出现列。与其使用一堆空值,不如使用一个单独的表,它与1:1相关,或者更贴切地说“1: 罕见”。然后只在需要这些列时才使用 LEFT JOIN。当需要将 NULL转换为 0时,使用 COALESCE()
底线: 视情况而定。

Limit 搜索条件 to one table. An INDEX cannot reference columns in different tables, so a WHERE clause that filters on multiple columns might use an index on one table, but then have to work harder to continue the filtering columns in other tables. This issue is especially bad if "ranges" are involved.
底线: 不要将这些列移动到单独的表中。

TEXT 和 BLOB 列可能非常庞大,这可能会导致性能问题,特别是在不必要地使用 SELECT *时。这样的列存储为“非记录”(在 InnoDB 中)。这意味着获取它们的额外成本可能包括额外的磁盘命中。
一句话: InnoDB 已经在处理这个性能“问题”了。