+4  A: 

The MySQL optimizer optimizes an IN (subquery) clause very badly. It performs nested query for each row of outer query.

To get the execution plan - just add EXPLAIN keyword right before your query

EXPLAIN SELECT ...
zerkms
I believe you're thinking of Correlated Subqueries, which do perform the query for each row of the outer query. A correlated subquery would include a column comparison from the outer query inside of the subquery. For example: SELECT t1.* FROM t1 WHERE t1.id IN (SELECT t2.id FROM t2 WHERE t2.name = t1.name);
Jimmy Z
A: 

Thanks zerkms!

I tried EXPLAIN on both SQLs, but it seems both of them hit the right index idxEventClosed (closingeventid, timeStart, eventCode). The explaining looks same exception the bold line below. I still don't have much idea about what caused the out of memory issue.

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)
Rick Wang
Use `INNER JOIN` - in this case `IN()` is much less performant solution.
zerkms
This should really be an addition to the question - rather than comments disguised as an answer. You can edit your own question.
Jonathan Leffler
Any one can give me any comment about the two execution plan above? I cannot understand how IN() is much less performance.
Rick Wang