2010-10-29 47 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

相关问题