2010-10-29 56 views
0

在我的MySQL數據庫中,表事件具有一個組合索引,其中包含列closingeventid,timeStart和eventCode。表事件中有超過2100萬行。IN和INNER JOIN在我的情況下有什麼區別?

這是兩個SQL,如果我在MySQL命令行中運行第一個SQL,進程mysqld-nt.exe的Mem Usage以每秒10 M的速度逐漸增加,它會上升到1.6 G左右,然後直線下降到30 M左右然後命令行返回Out of Memory異常。

但是,如果我使用第二個SQL,使用INNER JOIN而不是IN,那就沒關係。看來IN子句不會觸及任何索引。

爲什麼?任何想法來監視MySQL執行過程像MS SQL的執行計劃?

SELECT COUNT(*) AS 'cnt' 
FROM events 
WHERE 
    (timeStart < '2010-09-22 14:29:10’) 
AND (closingeventid IS NULL) 
AND (eventcode IN (SELECT DISTINCT evtcclosed FROM eventclose))` 

VS

SELECT COUNT(1) AS 'cnt' 
FROM events 
inner join 
      (SELECT DISTINCT evtcclosed FROM eventclose) ec 
    ON ec.evtcclosed = events.eventcode 
WHERE (timeStart < '2010-09-22 14:29:10’) AND (closingeventid IS NULL) 

回答

4

MySQL優化可優化IN (subquery)條款非常糟糕。它爲外部查詢的每一行執行嵌套查詢。

要得到執行計劃 - 只是你的查詢之前加EXPLAIN關鍵字權

EXPLAIN SELECT ... 
+0

我相信你正在考慮相關子查詢,它執行外部查詢的每一行查詢。相關的子查詢將包含來自子查詢內部的外部查詢的列比較。例如:SELECT t1。* FROM t1 WHERE t1.id IN(SELECT t2.id FROM t2 WHERE t2.name = t1.name); – 2010-10-29 03:36:22

0

感謝zerkms!

我試着EXPLAIN在兩個SQL上,但似乎他們都擊中了正確的索引idxEventClosed(closingeventid,timeStart,eventCode)。解釋看起來與下面的粗線相同。我仍然不清楚導致內存不足問題的原因。

mysql> EXPLAIN SELECT COUNT(*) AS 'cnt' FROM events WHERE (timeStart < '2010-10-29 14:29:10') AND (closingeventid IS NULL) AND (eventcode IN (SELECT D 
ISTINCT evtcclosed FROM eventclose)); 
+----+--------------------+------------+-------+-------------------------+----------------+---------+------+---------+------------------------------+ 
| id | select_type  | table  | type | possible_keys   | key   | key_len | ref | rows | Extra      | 
+----+--------------------+------------+-------+-------------------------+----------------+---------+------+---------+------------------------------+ 
| 1 | PRIMARY   | events  | range | idxStart,idxClosedEvent | idxClosedEvent | 17  | NULL | 4335955 | Using where; Using index  | 

| 2 | DEPENDENT SUBQUERY | eventclose | ALL | NULL     | NULL   | NULL | NULL |  10 | Using where; Using temporary | 

+----+--------------------+------------+-------+-------------------------+----------------+---------+------+---------+------------------------------+ 
2 rows in set (0.00 sec) 



mysql> EXPLAIN SELECT COUNT(1) AS 'cnt' FROM events inner join (SELECT DISTINCT evtcclosed FROM eventclose) ec on ec.evtcclosed = events.eventcode whe 
re (events.closingeventid is null) and (timeStart < '2010-10-28 14:29:10'); 

+----+-------------+------------+-------+---------------------------------+----------------+---------+------+---------+--------------------------+ 
| id | select_type | table  | type | possible_keys     | key   | key_len | ref | rows | Extra     | 
+----+-------------+------------+-------+---------------------------------+----------------+---------+------+---------+--------------------------+ 
| 1 | PRIMARY  | events  | range | evtNLoc,idxStart,idxClosedEvent | idxClosedEvent | 17  | NULL | 4330270 | Using where; Using index | 
**| 1 | PRIMARY  | <derived2> | ALL | NULL       | NULL   | NULL | NULL |  8 | Using where    |** 
| 2 | DERIVED  | eventclose | ALL | NULL       | NULL   | NULL | NULL |  10 | Using temporary   | 
+----+-------------+------------+-------+---------------------------------+----------------+---------+------+---------+--------------------------+ 
3 rows in set (0.00 sec) 
+0

使用'INNER JOIN' - 在這種情況下'IN()'是性能低得多的解決方案。 – zerkms 2010-10-29 03:27:30

+1

這應該是對問題的補充 - 而不是僞裝成答案的評論。你可以編輯你自己的問題。 – 2010-10-29 03:57:19

+0

任何人都可以給我關於上述兩個執行計劃的任何評論?我無法理解IN()的性能如何。 – 2010-10-29 04:46:02

相關問題