2013-10-29 61 views
5

這兩個之間的最佳查詢是什麼? 他們輸出相同的結果,期望一個人在where in內部執行條件,另一個在inner join內執行。內部聯接A和B上的選擇(A,B)vs mysql中選擇(A,B)中的(A,B)

select uv.* from version v inner join user_version uv ON v.id=uv.version_id 
WHERE (v.number, v.master_id) IN (
select max(v.number) as number, v.master_id 
    from version v inner join user_version uv ON v.id=uv.version_id group by v.master_id); 

select * from user_version uv 
    inner join version v on v.id=uv.version_id and v.number 
    inner join (
     select uv2.user_id, max(v2.number) maxNumber, v2.master_id master_id, v2.id version_id from version v2 
     inner join user_version uv2 on v2.id=uv2.version_id group by v2.master_id) test 
    on test.master_id=v.master_id and test.maxNumber=v.number ; 

我已經創建了一個例子的sqlfiddle:http://sqlfiddle.com/#!2/76001/62 (這樣做是爲了讓鏈接到特定用戶的「主」實體最大的版本)

如果您有其他的想法(我使用MySQL,所以我不能使用Windows功能)

感謝

+0

一般而言,像第二個那樣的「不相關子查詢」解決方案往往比其他方案更快。你的查詢有點複雜,但我認爲這個原則是成立的。 – Strawberry

回答

3

這不太容易回答這個問題。你應該知道一件重要的事情:MySQL把IN (<static values list>)IN (<subquery>)當作different queries。第一個等於範圍比較(如.. OR = .. OR =),而第二個等於= ANY() - 並不相同。因此,簡而言之,使用IN和子查詢將導致與ANY()查詢,即使子查詢是獨立的,MySQL也不會使用索引,並且返回靜態值列表。傷心,但是真的。 MySQL無法預測,所以即使它很明顯,索引也不會被使用。如果你使用JOIN(即重寫你的IN (<subquery>)) - 那麼如果可能的話,MySQL將使用索引JOIN條件。

現在,使用分區時,第二種情況可能約爲JOININ。如果你將使用JOIN--那麼,可悲的是 - 但是MySQL在一般情況下也不能預測JOIN的分區 - 並且它將使用整組分區。替換JOININ (<static list>)將改變EXPLAIN PARTITION圖片:MySQL將僅使用那些從IN子句中指定的範圍內選擇值所需的分區。但是,再一次,這不適用於IN (<subquery>)

作爲一個結論 - 很遺憾,當我們談論MySQL如何處理子查詢時IN - 並且通常情況下它不能安全地替換爲JOIN(這是關於分區情況)。所以,常見的解決方案是:與應用程序級別上主查詢分開的子查詢。如果我們談論的是獨立子查詢,返回靜態值列表,那麼這是最好的建議 - 那麼您可以將該值列表替換爲IN(<static list>)並獲得好處:MySQL將爲其使用索引,並且,如果我們談論分區,實際上需要從他們那裏使用。

+0

你是說第一個請求不會在master_id/number上使用索引,而第二個子選擇將返回所有匹配每行select的結果,而test.master_id = v沒有過濾器。 master_id條件? (在這種情況下,PARTITION的想法對我來說不是很清楚) – Quentin

+0

第一個不會使用'IN'子查詢的索引 –

相關問題