MySQL多对多表加入缓慢的性能

时间:2016-04-20 20:22:16

标签: mysql sql left-join mariadb

我有两个表,其中一个连接列具有多对多关系。每张表中有几十万条记录。我看到一些非常慢的查询性能,并且难以单独解决问题。

表-A:

+---------------------------+-------------+---------------+
| ID | Name varchar (30)    | Age int(3)  | Status int(1) |
+----+----------------------+-------------+---------------+
| 1  | Tom                  | 23          | 1             |
| 2  | Jerry                | 34          | 2             |
| 3  | Smith                | 21          | 1             |
| 4  | Ben                  | 46          | 5             |
+---------------------------+-------------+---------------+

表-B:

+---------------------------+-------------+---------------+
| ID | Name varchar (30)    | Sign int(3) | Status int(1) |
+----+----------------------+-------------+---------------+
| 1  | Tom                  | 12          | 1             |
| 2  | Smith                | 8           | 1             |
| 3  | Tom                  | 3           | 0             |
| 4  | Tom                  | 10          | 1             |
+---------------------------+-------------+---------------+

我需要获得表A中每个名字的年龄,表B中至少有一行,名称和状态(表B)为1。

我试过了:

SELECT Age FROM Table_A
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name
WHERE Table_B.Status=1;

这个查询花了很长时间我还没有等到它回来。 然后我尝试了:

SELECT DISTINCT Age FROM Table_A
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name AND Table_B.Status=1;

那回归非常快。 我进一步测试并尝试:

SELECT DISTINCT Age FROM Table_A
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name
WHERE Table_B.Status=1;

再次没有回来。

我对这里发生的事情感到困惑。

在上一个查询中,WHERE条件的行为是否与上一个查询的JOIN ON条件(Status = 1)相同?

为什么SELECT DISTINCT返回结果而不使用DISTINCT,这个过程需要永远?

4 个答案:

答案 0 :(得分:1)

对于多对多表,请勿包含AUTO_INCREMENT。是否PRIMARY KEY包含其他ID。有另一个索引。请使用InnoDB。

请参阅More details, plus rationale

答案 1 :(得分:0)

如果没有看到解释计划(或者MySQL的等价物),就不可能肯定地说。

我的猜测是,服务器知道您的if(suggestionsParsed[j].includes(testsParsed[i])){ txt4 = document.createTextNode(suggestionsParsed[j]); break; } SELECT DISTINCT OUTER JOIN' to table B is completely irrelevant when you use加入, so it just runs against table A and gets the Age values from there without even performing the外部联接“无关紧要?

在第一个查询中,服务器需要执行. Do you see why the以获得正确的行数。

当您在上一个查询中的JOIN子句中添加其他逻辑时,您已将其有效地转换为WHERE,所以现在INNER JOIN必须再次发生并且需要很长一段时间。

答案 2 :(得分:0)

确保在Table_A.Name,Table_B.Name和Table_B.Status列上设置了索引

答案 3 :(得分:0)

首先,你不需要LEFT JOIN,因为你只关心比赛:

SELECT a.Age
FROM Table_A a JOIN 
     Table_B b
     ON Table_A.Name = b.Name
WHERE b.Status = 1;

对于此查询,可以利用Table_B(status, name)Table_A(Name, Age)上的索引。