2012-04-01 61 views
8

我似乎有點卡住了。這是一個非常簡單的查詢。Mysql幫助需要通過子查詢優化組

如果我單獨運行查詢,它不是那麼慢,但是當我將它們組合起來時,它非常慢。

我不知道如何優化它。任何幫助將非常感激。我基本上只想顯示多個退款。所以faultid不止一次存在。

SELECT 
    r.* 
FROM 
    faultrefunds_v2 r 
WHERE 
    r.id IN (SELECT r1.id 
      FROM faultrefunds_v2 r1 
      GROUP BY faultid 
      HAVING count(r1.faultid) > 1); 

從結果解釋都已經被作爲附加的圖像

enter image description here

+0

是r.id的主要y鍵? – 2012-04-01 15:53:01

+0

是的,而faultid是外鍵 – 2012-04-01 15:59:22

+0

我認爲你寫的查詢不能回答這個問題。這是因爲一旦你通過faultid分組,你只會爲該faultid返回一個r.id。 – 2012-04-01 16:10:03

回答

1

我想,這個資格,而不是作爲一個重寫不是作爲一個優化,但這是我會嘗試,而不是:無論如何:

SELECT 
    r.* 
FROM faultrefunds_v2 r 
WHERE EXISTS (
    SELECT * 
    FROM faultrefunds_v2 r1 
    WHERE r1.faultid = r.faultid 
    AND r1.id <> r.id 
); 
+0

這也有效。 – 2012-04-01 16:39:42

+0

爲什麼這比我寫的查詢要快得多?他們看起來很相似? – 2012-04-01 16:42:06

+1

您的查詢使用分組,這是一個相對昂貴的操作,開始。此外,這種子查詢應該掃描整個表以構建匹配的行集。另一方面,我的查詢使用半連接(以'EXISTS'謂詞的形式)。在半連接中,只要找到至少一個匹配行就停止搜索,在某些/大部分行中存在許多匹配的情況下,您可以猜到,可以大幅提高查詢速度。 – 2012-04-01 17:08:48

1

我覺得你的查詢不回答這個問題。據我所知,你應該首先得到所有具有多個關聯id的faultid(表中的行)。然後獲取所有這些行(不只是faultId)。

試試這個:

select * from faultrefunds_v2 
where faultId in (
    select faultId from faultrefunds_v2 
    group by faultId 
    having count(*) > 1 
) 
+0

我認爲這是對我的查詢的改進,它更符合邏輯和解釋。但它仍然很慢。給它+1 – 2012-04-01 16:37:05

2

IN子句中,使用這將是非常緩慢的方式,使用JOIN代替:

SELECT r.* FROM ( 
    SELECT r1.id AS id 
    FROM faultrefunds_v2 r1 
    GROUP BY faultid 
    HAVING count(r1.faultid) > 1 
) AS ids 
LEFT JOIN faultrefunds_v2 AS r 
ON(ids.id = r.id) 
+0

這個作品,它的速度非常快。你能解釋爲什麼IN子句用我用它的方式很慢,所以我可以避免再做一次? – 2012-04-01 16:36:01

+1

MySql通常不會索引IN子句中的元素,因此它應該每次將'r'表中每行的id與子查詢中找到的所有id進行比較。在我的方法中,MySql查找所有適當的id,然後使用索引非常快速地爲外部查詢中的每個id檢索整行。 – nobody 2012-04-01 16:41:19

+0

這個答案是Andiry M反應的正確答案。我無法接受兩個答案(儘管我認爲可能對同一個問題有兩個正確但不同的答案)。 – 2012-04-02 08:29:07