MySQL超级慢内连接与group by

时间:2016-11-22 23:19:42

标签: mysql sql join group-by

我在加入下面的2个表时遇到问题。我需要的是第一个表中的所有部分,其中在第二个表中找到了clei OR部件号,并计算了表1中匹配的数量。

===================           ===================
table: svi                    table: svp
===================           ===================
id                            id
po                            price
customer                      clei
clei                          partNumber
partNumber                    description
====================          ===================

svi有大约100万行。 svp大约有2000个。这是我正在使用的联接......

SELECT svi.clei,
       svi.partNumber,
       count(*)
FROM    svp svp
   INNER JOIN
      svi svi
   ON    (svp.clei = svi.clei)
         OR (svp.partNumber = svi.partNumber)
GROUP BY svi.partNumber

查询运行时间超过2分钟,这看起来非常缓慢。 clei和partNumber在两个表中都被索引。我还能做些什么来加速这次加入?

1 个答案:

答案 0 :(得分:0)

索引在这里没有多大帮助,因为对于常量和WHERE运算符没有OR条件。

读取svp表的所有2000行;针对常量的条件减少了从表中读取的行数,但这里没有这样的条件。

然后,对于这2000行中的每一行,在svi表的索引中执行一次或两次查找以识别匹配的行。一个用于clei,如果没有成功,则另一个用于partNumber。或者反之亦然。

clei上的列partNumbersvi上的复合索引对此没有帮助;当使用OR组合条件时,它会有所帮助。

未使用表svp上的索引。如果svp上的索引包含cleipartNumber列,则MySQL可以决定在此处读取它,因为它包含的数据少于整个表。但它仍然会读取整个索引并处理所有行。它不能使用索引来过滤行,因为svp上没有过滤。

可能更糟糕(读取整个svi表并使用svp上的索引进行查找)但MySQL非常聪明,可以先处理较小的表。

EXPLAIN放在查询前面,将MySQL tells you (in less words)放在我上面尝试解释的内容中。

正如我在评论中所说,查询是无效的SQL。对于svi.partNumber的一个值,您可能拥有svi.clei的多个值。 GROUP BY svi.partNumber子句从表svi获取的具有partNumber相同值的所有行生成单个输出行。

但是,由于同一clei的{​​{1}}有两个或更多不同的值,因此partNumber子句中表达式svi.clei的最终值为不定。这意味着如果稍后再次运行相同的查询,或者在镜像数据库的其他服务器上运行它(或者在备份数据库之后再从备份恢复),它可以更改。

如果您忘记在SELECT条款中添加svi.clei,那么这只是一个简单的修复,但除此之外您必须重新考虑您的查询,因为它现在是,它没有&# 39; t产生你期望的结果。