2014-09-02 22 views
0

[問題摘要:2個SQL語句產生相同的結果,但速度不同。一個聲明使用JOIN,其他用途INJOIN快於IN]MySQL(版本5.5):爲什麼`JOIN`比`IN`子句快?

我嘗試了2種SELECT聲明對2個表,命名爲 booking_record夾雜。表夾雜物與表 booking_record有多對一的關係。

(不包括爲簡單起見表定義。)

首先聲明:(使用IN子句)

SELECT 
    id, 
    agent, 
    source 
FROM 
    booking_record 
WHERE 
    id IN 
    (SELECT DISTINCT 
     foreign_key_booking_record 
    FROM 
     inclusions 
    WHERE 
     foreign_key_bill IS NULL 
     AND 
     invoice_closure <> FALSE 
) 

第二語句:(使用JOIN

SELECT 
    id, 
    agent, 
    source 
FROM 
    booking_record 
    JOIN 
    (SELECT DISTINCT 
     foreign_key_booking_record 
    FROM 
     inclusions 
    WHERE 
     foreign_key_bill IS NULL 
     AND 
     invoice_closure <> FALSE 
) inclusions 
    ON 
    id = foreign_key_booking_record 

與300,000行在 booking_record - 表和6,100,000+行內含物 -table;第二個聲明在0.08秒內傳遞了127行,但第一個聲明花費了將近21分鐘的時間記錄。

爲什麼JOININ子句快得多?

+4

我建議你開始使用'EXPLAIN'兩個語句並查看結果來探討這個問題。 – 2014-09-02 13:30:14

+0

第二個還有一個過濾器'id = foreign_key_booking_record'。 – 2014-09-02 13:33:13

+0

性能差異的最可能解釋是生成的執行計劃中的差異。正如其他答案已經表明的那樣,'EXPLAIN'的輸出將顯示每個查詢的執行計劃。 IN(子查詢)的一個重大性能問題:MySQL可能對外部查詢返回的每一行執行子查詢。 – spencer7593 2014-09-02 14:09:12

回答

2

此行爲是詳細記錄。見here

簡短的回答是,直到MySQL版本5.6.6,MySQL在優化這些類型的查詢方面做得很差。會發生什麼情況是,外部查詢中的每一行都會運行子查詢。很多開銷,反覆運行相同的查詢。您可以通過使用良好的索引並從in子查詢中刪除distinct來改善此問題。

這是我更喜歡exists而不是in的原因之一,如果你關心性能。

1

EXPLAIN應該給你一些線索(Mysql Explain Syntax

我懷疑是版本正在建設一個名單,然後由每個項目掃描(IN被普遍認爲是非常低效的結構,我只使用它,如果我有項目的短名單,手動輸入)。

聯接是更有可能建造一個臨時表的結果,使得它更像是正常的表之間連接。

+0

Ollie打敗我,解釋它:P – Giles 2014-09-02 13:38:23

1

您應該通過使用EXPLAIN來探究這一點,如Ollie所說。

但是提前注意第二個命令有一個更多的過濾器:id = foreign_key_booking_record

檢查此具有相同的性能:

SELECT 
    id, 
    agent, 
    source 
FROM 
    booking_record 
WHERE 
    id IN 
    (SELECT DISTINCT 
     foreign_key_booking_record 
    FROM 
     inclusions 
    WHERE 
     id = foreign_key_booking_record -- new filter 
     AND 
     foreign_key_bill IS NULL 
     AND 
     invoice_closure <> FALSE 
)