2011-11-02 130 views
4

這是一個我從未得到確切答案的問題。我在這個例子中使用MySQL。SQL性能:哪個更快? IN()與JOIN

給定一組相當大的值(可以說500)。它是更快地使用這些值與在尋找一個表()子句:

SELECT * FROM table WHERE field IN(values) 

或者通過在內存中創建一個臨時表,用值填充,並將其加入到表被搜索:

CREATE TEMPORARY TABLE `temp_table` (`field` varchar(255) NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

INSERT INTO temp_table VALUES (values) 

SELECT * FROM table t1 JOIN temp_table t2 ON t1.field = t2.field 

兩種方法都會產生相同的結果集。

我已經完成了一些我自己的基本基準測試,發現處理超過500個值時,使用臨時表比IN()子句更快。

有人可以向我解釋MySQL的內部工作原理以及這個問題的正確答案是什麼?

感謝, 利奧

+0

請發佈您的基準,以便對它們進行驗證。你有領域的索引嗎? –

+1

你知道答案很大程度上取決於數據庫的結構嗎?創建臨時表,填充它並加入表涉及大量的CPU工作,與使用帶有IN運算符的查詢相反。由於內存存儲IO會更快,但是InnoDB也可以將其工作數據集保存在內存中。如果你根據InnoDB表的主鍵進行'IN'搜索 - 它會勝過臨時表。 –

+0

如果你也發佈瞭解釋計劃,這將會很有趣。 –

回答

2

從MySQL在線文檔,IN()

IN(值,...)

如果所有值都常數,他們是根據評估expr的類型和排序。 然後使用二進制搜索完成對項目的搜索。這意味着 如果IN值列表完全由常量組成,則IN非常快。 否則,根據第11.2節「表達式評估中的類型轉換」, 中描述的規則 進行類型轉換,但應用於所有參數。

考慮到我認爲使用IN()和一組常量是有意義的,否則應該在另一個表上使用子查詢。

你可以考慮usign EXISTS()而不是JOIN時,從其他表檢索項,它會顯著爲快大型數據集

SELECT * 
FROM table t1 
WHERE EXISTS 
     (
     SELECT * 
     FROM temp_table t2 
     WHERE t1.field = t2.field 
    ) 
+0

我不明白二進制搜索位。爲了這個工作,列需要被排序,因此可能被索引?那麼爲什麼不從索引中查找呢? (除非它們表示搜索使用二進制排序語義而不是談論實際[二進制搜索](http://en.wikipedia.org/wiki/Binary_search_algorithm) –

+0

@Martin Smith:二進制搜索(每個文檔只用於常量)當一組常量被排序時是有意義的,所以這意味着服務器會進行排序,然後只執行二進制搜索 – sll

+0

啊我明白了,我在想另一種方式,所以MySQL做了全表掃描,然後在每個值的常量列表?如果列被索引,並且in子句中只有兩個值,那麼如何處理?幾個索引查找肯定會更有效率? –

1

正確的答案取決於許多因素。

您已經完成了這項工作 - 如果您的基準測試告訴您使用臨時表的速度更快,那麼這就是要走的路。

如果更改硬件或顯着改變模式,請記住再次進行基準測試。