2013-08-06 67 views
1

我想查找在約500米的行表中有後續的所有小時記錄。JOIN和IN之間的MySQL性能差異

我嘗試:

SELECT DISTINCT (date_time) 
FROM my_table 
JOIN (SELECT DISTINCT (DATE_ADD(date_time, INTERVAL 1 HOUR)) date_offset 
     FROM my_table) offset_dates 
ON date_time = date_offset 

SELECT DISTINCT(date_time) 
FROM my_table 
WHERE date_time IN (SELECT DISTINCT(DATE_ADD(date_time, INTERVAL 1 HOUR)) 
        FROM my_table) 

在幾秒鐘的第一個完成,秒掛起小時。 我可以理解,越早越好,但爲什麼這麼巨大的性能差距?

--------編輯---------------

這裏是EXPLAIN對於兩個詢問

id select_type table  type possible_keys key  key_len ref       rows Extra 
1 PRIMARY  <derived2> ALL  NULL   NULL NULL NULL      1710 Using temporary 
1 PRIMARY  my_table ref  PRIMARY   PRIMARY 8  offset_dates.date_offset 555  Using index 
2 DERIVED  my_table index NULL   PRIMARY 13  NULL      5644204 Using index; Using temporary 


id select_type  table type possible_keys key  key_len ref  rows Extra 
1 PRIMARY   my_table range NULL   PRIMARY 8  NULL 9244 Using where; Using index for group-by 
2 DEPENDENT SUBQUERY my_table index NULL   PRIMARY 13  NULL 5129983 Using where; Using index; Using temporary 
+0

我可能是錯的,但它是非常重的子查詢。所以如果你用'JOIN'和'ON'子句執行它,速度會更快,因爲它不會檢索子選擇的每個結果。在第二個查詢中,您首先檢索子查詢的所有結果,然後查看它。 – Brewal

回答

2

在一般情況下,使用連接會比使用IN (...)等效查詢執行得更好,因爲前者可以在後者能夠」主動指數的優點查詢噸;必須掃描可能返回的每一行的整個IN列表。

(請注意,某些數據庫引擎的表現比其他人在這種情況下更好;例如,SQL服務器can produce equivalent performance for both types of queries

你可以看到什麼MySQL查詢優化器打算與給定SELECT查詢做在前面加上EXPLAIN到查詢並運行它。除此之外,這將爲您提供引擎在查詢中的每一步都必須檢查的行數;乘以這些計數以得到引擎將要訪問的總行數,這可以用作粗略估計可能的性能。

+0

謝謝,我添加了對查詢的解釋,但我在閱讀時遇到了一些麻煩! –

2

我都前綴通過explain查詢,然後比較訪問計劃中的差異。您可能會發現第一個查詢的行數比第二個少得多。

但我的直覺是JOIN比WHERE子句立即應用。因此,在WHERE子句中,您從my_table獲取每個記錄,應用算術函數,然後對它們進行排序,因爲select distinct通常需要排序,有時會在內存或磁盤上創建臨時表。檢查的行數可能是每個表的大小的乘積。

但是,在JOIN子句中,很多正在WHERE子句中檢查和排序的行可能會被預先消除。你可能最終只看到更少的行......而數據庫可能採取更簡單的措施來完成它。

但我認爲這個職位最好的回答你的問題:SQL fixed-value IN() vs. INNER JOIN performance

+0

謝謝,我在我的問題中加入了'EXPLAIN'。我在這種查詢計劃中不夠流暢,但顯然他們完全不同。 –

1

'IN'子句對於大型表格通常很慢。據我記得,對於你打印出來的第二條語句 - 它將簡單地循環遍歷my_table的所有行(除非你有索引),檢查每行WHERE子句的匹配。一般而言,IN被視爲一組具有所有設置元素的OR子句。 這就是爲什麼我認爲使用JOIN查詢後臺創建的臨時表更快。

以下是關於一些有用的鏈接:

MySQL Query IN() Clause Slow on Indexed Column

inner join and where in() clause performance?

http://explainextended.com/2009/08/18/passing-parameters-in-mysql-in-list-vs-temporary-table/

+0

謝謝,所有的事情都指向'JOIN',但我仍然對差異的程度感到困惑。 –

+1

考慮到Aaron Miller對我的one-IN子句的回答根本不使用索引,正如我所說的,只是簡單地循環查看每一行的表格,以匹配IN集合中的一組值;而JOIN首先構建臨時表(並且您正在使用此JOIN的索引,對嗎?),然後獲取行。 –

+1

這樣,遍歷500萬行將花費大量的時間(當然,實際上取決於一些數據庫設置和環境)。希望有所幫助。 –

1

另一個需要考慮的事情是與你的風格,未來的很少優化相比,可能加入。通過連接,你可以添加一個索引,這個索引取決於數據集,它可能會使速度提高2倍,5倍,10倍。使用IN,它將運行該查詢。