2014-12-23 37 views
3

我打破了我的頭在一個簡單的子查詢。我有以下查詢巫婆30秒以上運行:mySQL子查詢慢於2個單獨的查詢

SELECT DISTINCT SUBSTRING(6pp, 1, 4) AS postcode 
FROM 6pp 
WHERE gemeenteID 
IN (
    SELECT gebiedID 
    FROM tmp_orderimport 
    WHERE typeGebied = 'Gemeente' 
    AND idorder =1733 
    AND STATUS = TRUE); 

解釋: Explain

如果我打破了查詢2個查詢,先運行部分,整個事情的時間花費不超過一個多第二。但我當然更喜歡使用一個查詢。表格在MYISAM。有什麼建議麼?

更新:

以下是Gordon Linoff的例子。我改變了SQL語句:

SELECT DISTINCT SUBSTRING(6pp, 1, 4) AS postcode 
FROM `6pp` 
WHERE EXISTS (SELECT 1 
      FROM tmp_orderimport oi 
      WHERE oi.gebiedID = `6pp`.gemeenteID AND 
       typeGebied = 'Gemeente' AND idorder = 1733 AND STATUS = TRUE 
     ); 

而且在tmp_orderimport添加一個索引(gebiedID,typeGebied,idorder,狀態)。現在查詢運行時間在4秒以下。

新解釋: New SQL explain

+1

對於子查詢,MySQL是**真**不好。嘗試將該語句重寫爲連接(無論如何,這應該是可能的,因爲您正在使用「distinct」)。 –

+0

你可以編輯你的問題與查詢不會比一秒馬? –

回答

2

嘗試使用exists代替:

SELECT DISTINCT SUBSTRING(6pp, 1, 4) AS postcode 
FROM `6pp` 
WHERE EXISTS (SELECT 1 
       FROM tmp_orderimport oi 
       WHERE oi.gebiedID = `6pp`.gemeenteID AND 
        typeGebied = 'Gemeente' AND idorder = 1733 AND STATUS = TRUE 
      ); 

您也可以通過tmp_orderimport(gebiedID, typeGebied, idorder, status)上的索引來加速。

IN與子查詢結合使用時,MySQL可能效率低下(有時並取決於版本)。 EXISTS通常可以解決問題。具體的問題是每個比較都運行子查詢。當你創建一個臨時表時,你會繞過這個。

+0

我試過這個解決方案。但它仍然非常長(目前爲1米以上)。我有所有必填字段的索引。在所有字段中創建索引或者在其中的所有字段中創建索引有什麼不同? –

+0

@ DennisvanSchaik。 。 。是的,有很大的不同。雖然如果你有'tmp_orderimport(gebiedID)'的索引,查詢應該可能很好地工作,這取決於where子句的其餘部分的選擇性。 –

+0

EXPLAIN對這個查詢有什麼看法? –

1

使用INNER JOIN,而不是IN操作符

試試這個:

SELECT DISTINCT SUBSTRING(a.6pp, 1, 4) AS postcode 
FROM 6pp a 
INNER JOIN tmp_orderimport b ON a.gemeenteID = b.gebiedID 
WHERE b.typeGebied = 'Gemeente' AND b.idorder =1733 AND b.STATUS = TRUE 
0

可能MySQL爲主查詢的每條記錄運行一次子查詢。這最終導致指數級處理。

他的子查詢獨立於主查詢,可以先運行子查詢並將該值存儲在內存中(也許是臨時表),然後使用主查詢。

0

我沒有看到任何人對你的6pp表的評論,並有一個關於(gemeenteID,6pp)的索引。我也會在你的tmp_orderimport表(idorder,tpeGebied,status,gebiedID)上有一個索引,然後將它交換一下。

SELECT DISTINCT 
     SUBSTRING(P.6pp, 1, 4) AS postcode 
    FROM 
     (SELECT gebiedID 
      FROM tmp_orderimport 
     WHERE typeGebied = 'Gemeente' 
      AND idorder =1733 
      AND STATUS = TRUE) G 
     JOIN 6pp P 
     on G.gebiedID = P.gemeenteID