我有一个包含17个字段的用户表和一个包含40个字段的用户详细信息表,并且都使用user_id连接,user_id是用户表的主键。它们不是级联的 这两个表的行数最多为400,000到500,000 在我的软件中,大多数时候我需要加入这两个表来生成输出。
我的问题是,如果我删除用户详细信息表并将其字段放在用户表本身中,我的查询是否会运行得更快。因此我可以使用连接查询获得结果
哪一个更好 1)一个表中的所有字段或 2)两个表并使用连接查询
答案 0 :(得分:6)
我不是想成为一个聪明人,但唯一合理的答案是“试试并为自己衡量”。
你知道,你的问题中有太多未知变量:
WHERE
条件(如果有)JOIN
s,如果有的话尝试使用EXPLAIN
运行您的查询/查询;查询计划将为您提供比我们提供的更具体的数据。
答案 1 :(得分:3)
我建议您使用仅包含固定大小字段的主表。 (没有TEXT BLOB字段)。大多数时候这应该足够了。然后,只有在需要这些字段时才能加入第二个表格。
仅使用固定长度字段访问表比使用动态长度行更快。
另一个好的做法是使用最常用的列创建索引。如果所有列都在索引中,那么MySQL可以在不访问表的情况下为您提供结果(通过仅从索引读取数据)。
您必须考虑这些选项,但只有了解您在数据库上执行的操作的比例才能做出真正的决定。
答案 2 :(得分:2)
您的查询的答案很复杂。如果您的表包含要写入的字段,如果您的数据很冷或太大而无法保存在内存中,那将会更加复杂。它还依赖于存储引擎,存储引擎版本和其他一些东西。
只有通过基准测试才能获得稳定的结果。
但是,我可能会贡献一个有用的轶事。在另一项工作中,我们有一个用户数据库,它在一行中保存单个用户的所有数据。用户数据总共约为每用户1-2K,我们有2500万用户记录。数据库已经以每个8K的页面读取和写入数据(MySQL InnoDB将是16K页,顺便说一句)。这意味着每个数据库页面大约有4-6个用户记录,大约有500万页数据。
用户记录包含存储用户上次登录时间的字段。在早上7点到9点之间,我们会看到约有800万个独立用户登录,因此我们将有大约800万个页面被弄脏并且需要回写。基本上我们每天都会将整个用户表写回磁盘两次或三次。
我们引入了一个类似于用户和user_details页面的人为1:1关系:我们有一个用户和一个user_lastlogin表。 user_lastlogin记录非常狭窄,基本上只包含用户ID和用户的(三个不同的)上次登录时间(取决于所使用的服务)。因为user_lastlogin非常窄,所以我们现在每页有近千条记录,表中只有25.000页。有800万个独特的登录,我们现在需要回写更少的数据(因为数据库中的检查点和页面回写被延迟)。磁盘I / O负载下降了几个数量级。
经验教训:将静态数据与易失性数据分开是非常有用的(我们考虑了密码静态数据,因为我们每天有大约15.000次密码更改,而我们每天有800万次last_login更新)。
答案 3 :(得分:0)
最好将所有数据放在一个表中。否则,您正在反对数据库规范化规则。为什么要在2个表中分离关于一个用户的数据?只是通过不使用通配符选择器作为*来限制SELECT结果,但是使用请求的字段来制作列表。
答案 4 :(得分:0)
联接是一项相对昂贵的操作,所以如果你可以删除它们可能会加快速度。这是以标准化为代价的。
您可以通过脚本生成随机用户记录吗?如果是这样,您可以使用两个模式创建500,000条记录(一个表中的所有表和两个带连接的表)并查看哪个最快。可能差异太小,合并表没有意义。