4

我的表中有 40 多列,我必须添加更多字段,例如当前城市、家乡、学校、工作、大学、拼贴画..

这些用户数据将为许多匹配的用户提取,这些用户是共同的朋友(与其他用户朋友加入朋友表以查看共同的朋友)并且未被阻止并且还不是用户的朋友。

上面的请求有点复杂,所以我认为将额外的数据放在同一个用户表中以快速访问是个好主意,而不是向表中添加更多的连接,它会降低查询速度。但我想听听你的建议

我的朋友告诉我添加额外的字段,这些字段不会作为序列化数据在一个字段上进行搜索。



ERD图:



一些建议

  1. 这个表和列没有错
  2. 遵循这种方法MySQL:Optimize table with many columns - 将额外字段序列化为一个字段,不可搜索
  3. 创建另一个表并将大部分数据放在那里。(如果我已经有 3 个或更多表要加入来为用户提取记录(例如,朋友、用户、检查共同的朋友),这在加入时会变得更加困难)
4

4 回答 4

9

像往常一样 - 这取决于。

首先,MySQL 可以支持的列数是最大的,而您并不想到达那里。

其次,如果您有很多带有索引的列,则在插入或更新时会对性能产生影响(尽管我不确定这对现代硬件是否重要)。

第三,大表通常是所有看起来与核心实体相关的数据的垃圾场;这很快使设计变得不清楚。例如,您展示的设计显示了 3 个不同的“状态”类型字段(状态、is_admin 和 fb_account_verified) - 我怀疑有一些业务逻辑应该将它们链接在一起(例如,管理员必须是经过验证的用户),但是您的设计不支持。

这可能是也可能不是问题——它更多的是一个概念、架构/设计问题,而不是一个性能/它会起作用的问题。但是,在这种情况下,您可以考虑创建表来反映有关帐户的相关信息,即使它没有 x 对多关系。因此,您可以创建“user_profile”、“user_credentials”、“user_fb”、“user_activity”,所有这些都由 user_id 链接。这使它更整洁,如果您必须添加更多与 facebook 相关的字段,它们就不会悬在表格的末尾。但是,它不会使您的数据库更快或更可扩展。连接的成本可能可以忽略不计。

无论您做什么,选项 2 - 将“很少使用的字段”序列化为单个文本字段 - 都是一个糟糕的主意。您无法验证数据(因此日期可能无效,数字可能是文本,可能缺少非空值),并且在“where”子句中的任何使用都会变得非常缓慢。

一种流行的替代方法是“实体/属性/值”或“键/值”存储。此解决方案有一些好处 - 即使您的架构更改或在设计时未知,您也可以将数据存储在关系数据库中。但是,它们也有缺点:很难在数据库级别验证数据(数据类型和可空性),很难使用外键关系与其他表建立有意义的链接,查询数据可能变得非常复杂 - 想象一下找到所有status 为 1 且 facebook_id 为 null 且注册日期大于昨天的记录。

鉴于您似乎知道数据的架构,我会说“键/值”不是一个好的选择。

于 2013-01-09T13:13:48.547 回答
1

我建议进行一些测试。尝试两种方式并对其进行基准测试。没有人能够给你一个明确的答案,因为你没有分享你的硬件配置、示例数据、示例查询、你计划如何使用这些数据等。这里有一些你可能想要考虑的信息。

按预期使用数据库

关系数据库是专门为处理数据而设计的。就这样使用它。如果编写正确,在编写良好的模式中连接数据将表现良好。您可以使用 EXPLAIN 来优化查询。您可以记录慢速查询并提高其性能。数据库已经存在多年,如果将所有内容放在一个表中可以提高性能,您不认为这将成为互联网上的所有热门话题并且每个人都会这样做吗?

发动机类型

随着行数的增加,插入将如何受到影响?您使用的是 MyISAM 还是 InnoDB?您很可能希望使用 InnoDB,以便获得行级锁定而不是表。确保为您的表使用正确的引擎类型。获取您需要了解两者优缺点的信息。错误的发动机类型会影响性能。

使用分区提高性能

寻找提高性能的方法。例如,随着数据集的增长,您可以对数据进行分区。数据分区将通过将数据切片保存在单独的分区中来提高大型数据集的性能,从而允许您对大型数据集的部分而不是所有信息运行查询。

使用正确的列类型

考虑使用 UUID 主键来实现可移植性和未来增长。如果您使用正确的列类型,它将提高数据的性能。

不要序列化数据

使用序列化数据是更糟糕的方法。当您使用序列化字段时,您基本上是将数据库用作文件管理系统。它将保存和检索“文件”,但随后您的代码将负责反序列化、搜索、排序等。我花了一年时间试图解开这样的混乱。这不是数据库的用途。任何建议你这样做的人不仅给你不好的建议,而且他们不知道自己在做什么。在数据库中使用序列化数据的情况很少。

结论

最后,您必须做出最终决定。只需确保您充分了解并了解如何存储数据的利弊。我要给出的最后一条建议是找出 mysql 的重度用户在做什么。你认为他们将数据存储在一个表中吗?或者他们是否构建了一个关系模型并按照设计使用的方式使用它?

当你说“我要把所有东西都放在一个表中”时,你是在说你对性能有更多的了解,并且可以在代码中做出更好的选择来优化你的代码,而不是那些不断致力于 MySQL 以使其成为现实的开发人员团队是今天。考虑权衡您的知识与 MySQL 团队以及每天使用它的 DBA、公司和数据库社区成员的累积知识。

于 2013-01-17T05:18:20.943 回答
1

在某一点上,您应该看看“短行模型”,也称为实体键值存储,以及传统的“长行模型”。

如果您查看 WordPress 使用的架构,您会看到有一个包含 23 列的表 wp_posts 和一个包含 4 列(meta_id、post_id、meta_key、meta_value)的相关表 wp_post_meta。元表是一个“短行模型”表,它允许 WordPress 拥有无限的帖子属性集合。

“长排模型”或“短排模型”都不是最好的模型,通常最好的选择是两者的结合。正如@nevillek 指出的那样,搜索和验证“短行”并不容易,获取数据可能涉及旋转,这在 MySql 和 Oracle 中非常困难。

“长行模型”更容易验证、关联和获取,但当数据稀疏时,它可能非常不灵活且效率低下。某些行可能只有少数非空值。此外,您不能在不修改架构的情况下添加新列,这可能会导致系统中断,具体取决于您的架构。

我最近在一个金融服务系统上工作,每个工具都有 700 多个可能的事实,大多数只有不到 20 个事实。这可以通过设置几十个表来构建,每个表都针对特定的资产类别,或者作为一个包含 700 列的表,但我们选择使用一个包含大约 20 列(包含最流行的事实)的表和一个 4 列的组合包含其他事实的表格。这种设计效率很高,但访问起来很困难,因此我们在 PL/SQL 中构建了一些表函数来帮助解决这个问题。

于 2013-01-20T00:41:29.657 回答
0

我有一个一般性的评论给你,

想一想:如果你把超过 10-12 列的东西放在一个表中,即使把它们放在一个表中是有意义的,我想你会在短期、长期和中期付出代价。

您的 3 表方法似乎比 1 表方法更好,但考虑将它们制成 5-6 表而不是 3 表,因为您仍然可以。

currently, currently_position, currently_linkfromuser-tableworkfrom移动user-profile到一个新表中,主键名为USERWORKPROFILE.

将语言环境信息从新信息user-profile移到新USERPROFILELOCALE信息,因为它本质上是通用的。

是的,所有表中的所有通用属性都应该是int而不是varchar。例如,City 需要移出一个名为LIST_OF_CITIES 的新表,其中包含cityid. 并且您的属性city应该从 to 更改为varchar指向int并指向cityidLIST_OF_ CITIES

不用担心性能问题;您拥有的表越多,性能就越好,因为您实际上是将性能分配给数据库提供者,而不是全部掌握在自己手中。

于 2013-01-13T21:09:52.220 回答