2009-08-07 59 views
5

我想更好地理解爲什麼這個查詢優化如此重要(超過100倍),所以我可以重複使用類似的邏輯進行其他查詢。爲什麼MySQL JOIN比WHERE IN快(子查詢)

使用MySQL 4.1 - RESET QUERY CACHE和FLUSH TABLES在所有查詢和結果時間都可以一致地複製之前完成。只有在EXPLAIN中對我而言顯而易見的是在JOIN期間只需要找到5行。但是,這是速度的全部答案?兩個查詢使用的局部索引(forum_stickies),以確定刪除的主題狀態(topic_status = 0)

截圖用於更深入的分析EXPLAIN

慢查詢:0.7+秒(緩存清除)

SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics 
WHERE topic_last_post_id IN 
(SELECT SQL_NO_CACHE MAX (topic_last_post_id) AS topic_last_post_id 
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id) 

快速查詢:0.004秒或更少(清除緩存)

SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics AS s1 
JOIN 
(SELECT SQL_NO_CACHE MAX(topic_last_post_id) AS topic_last_post_id 
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id) AS s2 
ON s1.topic_last_post_id=s2.topic_last_post_id 

請注意,最重要的列(topic_last_post_id)上沒有索引,但無法幫助(結果存儲以供重複使用)。

答案僅僅是因爲第一個查詢必須掃描topic_last_post_id TWICE,第二次將結果與子查詢進行匹配?如果是這樣,爲什麼它指數更慢?

(不那麼重要我很好奇,爲什麼第一個查詢仍然需要很長時間,如果我竟然穿上topic_last_post_id索引)

更新:我發現了計算器後來經過一番搜索這個線程上進入這個話題Subqueries vs joins

回答

4

也許引擎爲bb_topics中的每一行執行子查詢,只是爲了查看它是否在結果中找到topic_last_post_id。會是愚蠢的,但也會解釋巨大的差異。

+1

哇,這可能是可能的。我只考慮過它可能會查詢組中每個id的結果(其中5個),但現在你提到了它,我想知道它是否適用於所有209行(甚至更差的293行)。 我向某人發出了一個請求,試圖在一個更大的數據集上進行查詢(10,000行vs 300),以便我看到問題是否會變得更加放大,從而證明理論。 – 2009-08-07 14:38:32

+1

剛剛發生,我也嘗試這個簡單的查詢'SELECT SQL_NO_CACHE forum_id,topic_id從bb_topics WHERE topic_last_post_id IN(1516,1567,1572,1569,1578)',它非常快。所以你是對的,它正在爲每一行執行子查詢,哇,這太瘋狂了。 – 2009-08-07 14:53:22

+0

這似乎是固定在5.6(它不是一個''依賴子查詢'''),性能類似於JOIN。 – Vatev 2014-04-03 11:34:20

0

我會說,因爲IN()子句中的參數可以是任何你堅持在那裏,數據庫必須檢查返回的一切。當你加入表格時,有很多使用的性能增強策略,例如它可能使用索引來獲得優勢。