2016-11-22 88 views
0

我在加入下面的2個表時遇到問題。我需要的是所有在CLEI或部件號在第二個表中找到的第一個表的零件,與相匹配多少計數有從表1MySQL超級緩慢內部加入組

===================   =================== 
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

(離題)如果'partNumber'不是表'svi'的'PK',那麼你的查詢就是無效的SQL。即使MySQL接受它,它也會自由地從SELECT語句中返回表達式svi.clei所需的值。 http://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html – axiac

+0

您的'GROUP BY'也缺少SELECT語句中的非聚合列之一 – Phil

+0

是菲爾那是故意的。每個partNumber只能有1個clei,但每個clei可以有多個partNumber。按partNumber分組只能完成我想要做的事情。 – scott80109

回答

0

這裏的索引沒有什麼幫助,因爲對常量沒有WHERE條件,並且因爲OR運算符。

讀取所有2000行的svp表;針對常量的條件減少了從表中讀取的行數,但這裏沒有這樣的條件。

然後,對於這2000行中的每一行,在svi表的索引中執行一個或兩個查找以標識匹配的行。一個用於clei,如果不成功,另一個用於partNumber。或相反亦然。

svi上的列cleipartNumber上的複合索引對此沒有幫助;當條件合併使用OR時,它會有所幫助。

未使用表svp上的索引。如果在svp上包含cleipartNumber列的索引,那麼MySQL可以決定在這裏讀取它,只是因爲它包含的數據少於整個表。但它仍然讀取整個索引並處理所有行。它不能使用索引來過濾行,因爲svp上沒有過濾。

它可能更糟糕(閱讀整個svi表並使用svp上的索引進行查找),但MySQL足夠智能,可以先處理較小的表。

EXPLAIN放在你的查詢和MySQL tells you (in less words)之前我試着在上面解釋一下。


正如我在評論中所說,查詢是無效的SQL。對於svi.partNumber的一個值,您可能有多個值爲svi.cleiGROUP BY svi.partNumber子句從表svi中獲得的所有行中的單個輸出行具有相同的值partNumber

但是,因爲存在用於clei兩個或更多個不同的值相同partNumber,最終值它圖片從SELECT子句表達svi.clei是不確定的。這意味着,如果稍後再運行相同的查詢,或者如果在反映數據庫的其他服務器上運行它(或者在備份數據庫並從備份中恢復之後),它可能會更改。

如果你只是忘記了GROUP BY子句中添加svi.clei那麼它是一個容易解決;否則,您必須重新考慮你的查詢,因爲它是現在,也不會產生預期的結果。

+0

我故意排除了group by子句中的svi.clei,因爲單個clei可以有多個partNumber。例如,3層不同的部分看起來是這樣的.... CLEI/PARTNUMBER BAC3SY4EAB/11540A-REV-01 BAC3SY4EAB/11540A-REV-02 BAC3SY4EAB/11540A-REV-03 所以我想知道如果我有第一個8個,第二個10個,第四個或第三個。 – scott80109

+0

而且查詢似乎是有效的,因爲每次運行時我都會得到準確的結果。它只是極其緩慢。 – scott80109

+0

如果單個'clei'有多個'partNumber',它按預期工作(但它仍然是無效的SQL)。您可以在svi.partNumber後面將'svi.clei'放入'GROUP BY'子句中。雖然這可以修復查詢,但它並沒有提高速度:-(問題出現的時候是另一種方式:一個'partNumber','clei'的多個值。 – axiac