这里的连接似乎没必要

时间:2015-11-05 21:18:25

标签: mysql performance join query-optimization

TableA
------
id
Name
other_fields

TableB
------
A_id (foreign key to TableA.id)
other_fields

TableB中选择参与TableA中具有特定属性的条目(例如Name = "Alice"

的条目

这可以通过联接轻松完成:

SELECT TableB.*
FROM TableA INNER JOIN TableB on TableA.id = TableB.A_id
WHERE TableA.Name = "Alice"

习惯于程序化编程,加入似乎有点过分和不必要,因为我们实际上不需要来自TableA id以外Alice的任何信息。 1}}。

所以 - 假设Alice是唯一的 - 有办法做到这一点(伪代码):

variable alice_id = get id of Alice from TableA

SELECT *
FROM TableB
WHERE A_id = alice_id

如果是,是否应该使用传统的JOIN方法?它更快吗? (当然,原则上)

2 个答案:

答案 0 :(得分:3)

你问你是否可以这样做:

SELECT * FROM TableB WHERE A_id = (SELECT id FROM TableA WHERE Name = 'Alice');

这是一个完全合法的查询,但MySQL会更好地执行连接,因为子查询被视为第二个单独的查询。使用MySQL EXPLAIN命令(只需将其置于SELECT查询之前)将显示用于查询的索引,临时表和其他资源。当一个查询比另一个查询更快或更有效时,它应该让您知道。

答案 1 :(得分:1)

对于您的工作负载和索引,您应该尝试查询的执行计划和运行时。在任何一种情况下,您都可以从名称上获得索引。

我相信这两个查询最终都会有类似的计划。我们来检查一下。

创建表格

create table tablea (id int primary key, nm as varchar(50));
create index idx_tablea_nm on tablea(nm);
create table tableb(a_id int, anotherfield varchar(100), 
      key idx_tableb_id(a_id), 
      constraint fk_tableb_tablea_id foreign key (a_id) references tablea (id));

让我们在第一个上做EXPLAIN

explain select tableb.* from tablea inner join tableb on tablea.id = tableb.a_id where tablea.nm = 'Alice';
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+
| id | select_type | table  | type | possible_keys         | key           | key_len | ref               | rows | Extra                    |
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+
|  1 | SIMPLE      | tablea | ref  | PRIMARY,idx_tablea_nm | idx_tablea_nm | 53      | const             |    1 | Using where; Using index |
|  1 | SIMPLE      | tableb | ref  | idx_tableb_id         | idx_tableb_id | 5       | tablea.id         |    1 | Using where              |
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+

让我们在第二个问题上做EXPLAIN

explain select * from tableb where a_id = (select id from tablea where nm = 'Alice');
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+
| id | select_type | table  | type | possible_keys | key           | key_len | ref   | rows | Extra                    |
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+
|  1 | PRIMARY     | tableb | ref  | idx_tableb_id | idx_tableb_id | 5       | const |    1 | Using where              |
|  2 | SUBQUERY    | tablea | ref  | idx_tablea_nm | idx_tablea_nm | 53      |       |    1 | Using where; Using index |
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+

我在这些表中没有太多数据,只有很少的数据,您会注意到相同的性能。随着工作负载的变化,执行游戏可能会更改。