2012-08-29 43 views
3

我有一堆代碼,通過它們的ID在數據庫中查找一些CD。這是使用'IN'條件完成的:MySQL和性能:使用'IN'還是'JOIN'?

(1) SELECT * FROM album WHERE id IN (?,?,?,?,?) 

下一步是獲取與這些專輯相關的曲目。我通過修改'base'查詢來做到這一點。

(2) SELECT track.* FROM album 
LEFT JOIN track ON track.album_id = album.id 
WHERE album.id IN(?,?,?,?,?) 

現在,我已經有了專輯和曲目。但是,我需要加載曲目的作曲者詳細信息。出於幾個原因,我無法與上述查詢一起完成,因此我需要單獨執行。

我可以做的是根據曲目查找作曲家,在那裏使用曲目ID並根據這些曲目ID查找作曲家表中的作曲家。或者,我可以更進一步修改「基本」查詢,並再次使用composers表進行連接。然而;這裏有一個通用的規則(關於表現),它容易指出其中一個詢問有利嗎?我已經測試了一點,但我已經做了這樣一個小規模的,我實在看不出有什麼區別...

(3) SELECT composer.* FROM album 
LEFT JOIN track ON track.album_id = album.id 
LEFT JOIN composer ON composer.track_id = track.id 
WHERE album.id IN (?,?,?,?,?) 

......或者......

[get track ids from query (2)] 

(4) SELECT composer.* FROM composer 
WHERE composer.track_id IN (?,...); 

爲了記錄:我已經在所有標準和連接列上都有索引。

+0

您是否可以在工作臺中運行兩個查詢,然後比較結果? –

+0

一般規則是,你應該總是'加入'。 – Jon

+0

你有多少個track id? sql字符串可能會變得非常大。 – edze

回答

5

因爲你只關心作曲家,所以沒有理由在查詢3中使用LEFT JOIN(好讓你給他們編號)。 (一般來說,外連接速度較慢。)

您無需加入查詢3中的相冊表 - 只需使用track.album_id上的IN即可。 (我想你不擔心流氓曲目丟失專輯。)

你提到你有各種各樣的索引。但請記住,MySQL只能爲每個查詢的每個表使用一個索引。所以如果你有多件事要檢查你必須做一個複合索引。

令人驚訝的是,做一個連接通常比一個大的IN語句快,這是因爲IN中的值沒有被索引,所以MySQL無法對它們進行索引連接。但是這隻適用於很多值 - 對於少數使用IN的人來說可能會更快。

就個人而言,我會使用JOIN方法,直到您看到此查詢成爲問題。 (只有當你有一些非常複雜的條件才能檢查,這可能會發生兩次)。連接是更簡單的代碼,並且很可能會超快 - 所以不要讓事情變得更復雜,沒有特定的原因。

+0

感謝您的回答。在查詢中看到100-500個跟蹤ID並不罕見,所以它可能很容易成爲不少。關於額外連接(數字3)...我無法刪除它,因爲我的代碼重新使用查詢並修改它們以獲取關聯的數據。我需要這樣做,因爲查詢可能會發生很大的變化,我無法真正預測'基本'查詢會是什麼樣子。 – sbrattla

+1

如果你使用這樣的外連接,期望一些完全空白的行,你必須在你的前端語言中進行過濾。有了500個ID,這是一個不容易的事情:使用連接。 – Ariel

+0

感謝您的反饋! – sbrattla