在我的情况下,IN和INNER JOIN有什么区别?

时间:2010-10-29 02:56:58

标签: mysql

在我的MySQL数据库中,表事件有一个复合索引,其中包含列lidingeventid,timeStart和eventCode。表事件中有超过2100万行。

这是两个SQL,如果我在MySQL命令行中运行第一个,进程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)

2 个答案:

答案 0 :(得分:4)

MySQL优化器非常糟糕地优化IN (subquery)子句。它为外部查询的每一行执行嵌套查询。

要获得执行计划 - 只需在查询之前添加EXPLAIN关键字

EXPLAIN SELECT ...

答案 1 :(得分:0)

谢谢zerkms!

我在两个SQL上尝试了EXPLAIN,但似乎它们都遇到了正确的索引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)