MySQL子查询真的很慢...解决方法?

问题描述:

我已经在MySQL 5.0,5.1,5.5上测试了以下看似简单的查询,发现它非常慢。MySQL子查询真的很慢...解决方法?

select * from entry where session_id in 
    (select session_id from entry where created_at > [some timestamp]) 

多个条目可以具有相同的会话ID,但具有不同的created_at时间戳。 该查询旨在获取所有条目的来自同一个session_id,其created_at大于指定时间戳的至少一个条目。

我已经看到其他人谈到类似查询的MySQL子查询性能问题,并且MySQL认为子查询是一个依赖查询,并且它正在对外部查询执行全表扫描。建议的解决方法是这样的:

select * from entry where session_id in 
    (select session_id from 
     (select session_id from entry where created_at > [some timestamp]) 
    as temp) 

但是,这种黑客不适合我,并使其更慢。

有关如何重写此查询的任何想法?

根据您的数据分发,使用此

SELECT e.* 
FROM (
     SELECT session_id, MAX(created_at) 
     FROM entry 
     GROUP BY 
       session_id 
     HAVING MAX(created_at) > $mytimestamp 
     ) ed 
JOIN entry e 
ON  e.session_id = ed.session_id 

(创建(session_id, created_at)索引),或这样的:

SELECT DISTINCT e.* 
FROM entry ed 
JOIN entry e 
ON  e.session_id = ed.session_id 
WHERE ed.created_at > $mytimestamp 

(创建created_at和两个单独的索引session_id

+0

你达人。谢谢! 我从第二个查询开始,但忽略了不同。我不知道你可以使用通配符将不同的结果应用于整个结果集。真棒。 – n00b 2011-05-13 22:05:28

如何:

SELECT DISTINCT e2.* 
    FROM entry e1 
     INNER JOIN entry e2 
      ON e1.session_id = e2.session_id 
    WHERE e1.created_at > [some timestamp] 

如果您还没有他们,就created_atsession_id指标很可能是有帮助。

+0

你还需要'group by e2.id',否则你会得到重复的。 – 2011-05-13 22:02:07

+0

谢谢。实际上,这是我最初尝试的。这是给我重复。对我来说没有发生过使用分组。或者你可以使用不同的e2。*。 – n00b 2011-05-13 22:05:07

+0

新增更正。 – 2011-05-13 23:02:38

我也有一个双子查询技巧的问题, btw我刚刚发现,使用这个工作对我来说(根据您的查询):

select * from entry where session_id in 
    (select (select session_id from entry where created_at > [some timestamp])) 

在我的情况下,原有的查询可以使用一个连接或“正常”双子查询招小时,与修改后的双子查询用了0秒工作: )

+1

这是非常有用的,因为很容易申请!然而奇怪的是MySQL的这种行为...... – Pisu 2011-10-03 16:32:55

+1

只有在内部查询返回单个结果的情况下,这才起作用。否则,你会得到错误“子查询返回多于一行” – ecdeveloper 2015-10-26 23:19:43