我在加入下面的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在两个表中都被索引。我还能做些什么来加速这次加入?
答案 0 :(得分:0)
索引在这里没有多大帮助,因为对于常量和WHERE
运算符没有OR
条件。
读取svp
表的所有2000行;针对常量的条件减少了从表中读取的行数,但这里没有这样的条件。
然后,对于这2000行中的每一行,在svi
表的索引中执行一次或两次查找以识别匹配的行。一个用于clei
,如果没有成功,则另一个用于partNumber
。或者反之亦然。
表clei
上的列partNumber
和svi
上的复合索引对此没有帮助;当使用OR
组合条件时,它会有所帮助。
未使用表svp
上的索引。如果svp
上的索引包含clei
和partNumber
列,则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产生你期望的结果。