我最近訪問過一個有趣的求職面試。在那裏我被問了一個關於使用包含長標量列表(即成千上萬個值)的WHERE..IN
子句來優化查詢的問題。這個問題不是關於IN
子句中的子查詢,而是關於簡單的標量列表。優化:WHERE x IN(1,2 ..,100.000)vs INNER JOIN tmp_table USING(x)?
我馬上回答,這可使用INNER JOIN
與另一個表(可能臨時一個),這將僅包含那些標量進行優化。我的回答被接受了,並且有評論者的一條評論說,「目前沒有數據庫引擎可以優化足夠高性能的條件」。我點了頭。
但是,當我走了出來,我開始有些懷疑。這種情況似乎相當微不足道,廣泛用於現代RDBMS,無法對其進行優化。所以,我開始了一些挖掘。
的PostgreSQL:
看來,PostgreSQL所parse scalar IN()
constructions into ScalarArrayOpExpr
structure,這是sorted。此結構稍後將在索引掃描期間用於查找匹配的行。 EXPLAIN ANALYZE
這樣的查詢只顯示一個循環。沒有連接完成。所以,我期望這樣的查詢比INNER JOIN更快。我對我現有的數據庫進行了一些查詢,我的測試證明了這一點。但我不在乎測試純度,Postgres處於Vagrant之下,所以我可能是錯的。
MSSQL服務器:
MSSQL服務器builds a hash structure from the list of constant expressions and then does a hash join with the source table。即使沒有排序似乎完成,我認爲這是一場表演賽。我沒有做任何測試,因爲我對這個RDBMS沒有任何經驗。
MySQL服務器:這個問題
The 13th of these slides說,這5.0之前的確發生在MySQL的一些情況。但除此之外,我沒有發現任何其他與治療不良有關的其他問題。不幸的是,我沒有找到任何反證的證據。如果你有,請踢我。
SQLite的:
Documentation page暗示了一些問題,但我傾向於相信事情說明真的有在概念層面。沒有其他信息被發現。因此,我開始認爲我誤會了我的面試官或誤用了Google;)或者,也許是因爲我們沒有設置任何條件,我們的談話變得有點模糊(我們沒有具體說明任何具體情況RDBMS或其他條件,這只是抽象的談話)。
它看起來像天,其中數據庫改寫IN()
爲一組OR
報表(可以在列表中與NULL
值有時會造成問題,順便說一句)是很久以前。或不?
當然,在情況下,標量的列表長於允許數據庫協議包,INNER JOIN
可能是唯一的解決方案。
我認爲在某些情況下,查詢解析時間(如果沒有準備的話)單獨可以殺死性能。
此外,數據庫可能無法準備IN(?)
查詢,這將導致一次又一次地重新分析(這可能會導致性能下降)。實際上,我從來沒有嘗試過,但我認爲即使在這種情況下,與查詢執行相比,查詢解析和規劃並不是很大。
但除此之外,我沒有看到其他問題。那麼,除了有這個問題的問題。如果您有查詢,其中包含數千個ID,則您的架構出現問題。
是嗎?
從我的經驗來看,SQL Server在大量IN參數上獲取查詢規劃器超時。 –
雖然有趣,它不適合這個網站。你知道......我正在投票結束。 –
我寫了[This thing](http://stackoverflow.com/a/34015333),它與隨機數有關。我做了端到端的工作。我所說的附錄C在列表中使用較多。一千個元素。結果是每秒2秒。 – Drew