为啥对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快?

Posted

技术标签:

【中文标题】为啥对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快?【英文标题】:Why is a union mysql query over three tables faster than join on impossible where clauses?为什么对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快? 【发布时间】:2016-11-28 22:12:12 【问题描述】:

我的架构设置为具有三个表playercoachmanager,其中三个表都有一个表employee 的外键,其中包含不超过一个自动递增ID 和一个字符串type 代表他们的员工类型,即。 “球员”或“教练”或“经理”。

但是,不同的员工根据他们工作的团队有不同的 ID。所以我有一个查找表team_x_lookup 用于每个团队(其中 x 是团队编号或名称),它将团队 ID 映射到全局 ID。此外,对于每个包含团队 ID 的团队,我在每个 player coachmanager 表中都有一个生成的列,该列被索引。如果员工不在该团队中,则此列显然为空。

要从员工的团队 ID 中获取员工,我目前有两个选择语句

SELECT * FROM employee e
    LEFT JOIN player p ON (e.`type` = 'PLAYER' AND p.employee_id = e.id)
    LEFT JOIN coach c ON (e.`type` = 'COACH' AND c.employee_id = e.id)
    LEFT JOIN manager m ON (e.`type` = 'MANAGER' AND m.employee_id = e.id)
WHERE e.id = (
    SELECT employee_id FROM team_x_lookup t WHERE t.team_id = 6
);

SELECT * FROM (
    SELECT * FROM player WHERE team_id = 6 
    UNION
    SELECT * FROM coach WHERE team_id = 6
    UNION 
    SELECT * FROM manager WHERE team_id = 6
) as emp;

我对所有我执行 SELECT 的操作都有索引。运行解释分别给了我这些:

1   PRIMARY e       const   PRIMARY,id_UNIQUE           PRIMARY 4   const   1   100.00  
1   PRIMARY p       const   PRIMARY,employee_id _UNIQUE PRIMARY 4   const   1   100.00  
1   PRIMARY c       const   PRIMARY,employee_id _UNIQUE PRIMARY 4   const   0   0.00    unique row not found
1   PRIMARY m       const   PRIMARY,employee_id _UNIQUE PRIMARY 4   const   0   0.00    unique row not found
2   SUBQUERY t      const   PRIMARY,team_id_UNIQUE      PRIMARY 4   const   1   100.00  

1   PRIMARY         <derived2>      ALL                                 6               100.00  
2   DERIVED         player          ref team_x_id_INDEX team_x_id_INDEX 5   const   1   100.00  Using index
3   UNION           coach           ref team_x_id_INDEX team_x_id_INDEX 5   const   1   100.00  Using index
4   UNION           manager         ref team_x_id_INDEX team_x_id_INDEX 5   const   1   100.00  Using index
N   UNION RESULT    <union2,3,4>    ALL                                                         Using temporary

我不喜欢第二种方式,因为它需要我为每个表增加 20 列。但是,我不明白联合查询如何比查找表查询快 50%!联合不是必须在所有三个表上进行选择,而交叉引用查询会注意到三个连接之一是可能的并丢弃另外两个?

我想知道如何使交叉引用表更快,另外因为联合要求我从联合中的每个表中选择相同数量的列,而我的每个表都有不同数量的列,所有这些都应该是返回。

编辑

我在数据库中有大约 30,000 个元素,我正在通过联合查询数据的前半部分和通过联接查询数据的后半部分来进行计时。我的时间大约为 union 3.9s 和 join 7.0s。

【问题讨论】:

请给DDL。阅读并采取行动minimal reproducible example。搜索Stack Overflow re bad idea“智能键”,在键值中编码信息。 team_x_lookup 也是一个坏主意,您在表名中编码信息。只需从简单的设计开始,其中所有信息都记录为表格行中的值。每个表都有一个相关联的谓词句子模板),并包含一些行,这些行说明了列值替换列名时的情况。 PS 您对 NULL 的使用似乎会使您的表格超出必要的范围,每一行都需要进行不必要的计算。 【参考方案1】:

您可能可以通过删除子查询使第一个查询更高效,如下所示:

SELECT e.* FROM employee e
INNER JOIN team_x_lookup t ON e.id = t.employee_id
LEFT JOIN player p ON (e.`type` = 'PLAYER' AND p.employee_id = e.id)
LEFT JOIN coach c ON (e.`type` = 'COACH' AND c.employee_id = e.id)
LEFT JOIN manager m ON (e.`type` = 'MANAGER' AND m.employee_id = e.id)
WHERE t.team_id = 6

【讨论】:

谢谢,这使查询更简单,但不会改变执行时间 还不错。通常子查询可能是一个问题,但在这种情况下显然不是。

以上是关于为啥对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快?的主要内容,如果未能解决你的问题,请参考以下文章

mysql 多表联合查询啥用

记一次MySql优化问题

mysql基础3

『 MySQL篇 』:MySQL表的聚合与联合查询

数据库(比如MYSQL) ,表连结查询与子查询哪个效率高些? 为啥

mysql多表left join联合查询效率问题5