内部连接的MySQL Query非常慢

时间:2016-01-28 17:13:50

标签: mysql sql database join

我有两个表,每个表包含6M行。我尝试使用内部联接加入这两个,但查询运行了2天而没有完成。加入是(注意我使用count(*)只是为了让我能够运行解释,我实际上在CTAS中使用join):

SELECT count(*)
FROM table1 t1,
     table2 t2
WHERE t1.col1 = t2.colA
  AND t1.col2 = t2.colB;

经过一番调查后,我发现以下查询运行良好:

SELECT count(*)
FROM
  (SELECT *
   FROM table1) t1,

  (SELECT *
   FROM table2) t2
WHERE t1.col1 = t2.colA
  AND t1.col2 = t2.colB;

除了表之间的唯一区别,我使用子查询SELECT * FROM table;

运行解释计划表明后一个查询在选择table2时正在构建索引。而第一个查询使用连接缓冲区(块嵌套循环)。

当然MySQL非常聪明,可以确定这两个查询实际上是相同的,并且对两个查询都一样吗?我不明白为什么需要索引,因为无论如何都需要对两个表进行全面扫描。这些是临时/暂时表,所以如果我确实放了一个索引,它实际上就是执行这个连接。

有没有办法通过MySQL配置解决这个问题?

1 个答案:

答案 0 :(得分:1)

你需要至少有一个表的索引,甚至是

create index Temp1 on Table2 ( colA, colB )

因此,表1中的查询加入到表2中,因此即使表1中的表扫描都在表1中,您也需要它来快速查找表2中匹配的记录。如果NEITHER有索引,然后这样想。对于Table1中的每条记录,扫描表2中的所有记录并获取与ColA,ColB匹配的所有记录。现在,返回表1中的SECOND记录...返回表2中的所有记录,直到找到匹配为止。

由于你有6M的记录,你几乎可以在性能上扼杀一头牛(可以这么说)。通过索引,即使在SECOND表上,当查询在第一个记录上时,它可以立即跳转到与ColA,ColB匹配的行,并且一旦完成这些A / B记录,它就会返回到第一个表

现在,其他开销效率。如果您在各自的Col1,Col2和ColA,ColB上都有索引的BOTH表,那么引擎将在其内存/缓存中为每个公共区域提供整个记录块,而不必继续返回原始数据页其他元素反复出现。

因此,即使您认为它可能不实用,处理大型表查询仍然很好。此外,如果第一个表中的多个记录具有相同的Col1,Col2值,但是对于表中的其他列具有不同的其他值,并且类似地在多个ColA,ColB的第二个表中,您将获得笛卡尔结果。请考虑以下情况

Table1
Col1  Col2  OtherColumn
X     Y     blah1
X     Y     blah2
X     Y     blah3


Table2
ColA  ColB  OtherColumn
X     Y     second blah1
X     Y     second blah2
X     Y     second blah3

像你这样的简单查询

SELECT count(*)
FROM table1 t1,
     table2 t2
WHERE t1.col1 = t2.colA
  AND t1.col2 = t2.colB;

将导致计数为9.您有6M记录和可能的笛卡尔结果?希望这能澄清您可能遇到的一些问题。