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

时间:2011-05-13 21:31:21

标签: mysql performance subquery

我在MySQL 5.0,5.1,5.5上测试了以下看似简单的查询,发现它非常慢。

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

多个条目可以具有相同的会话ID,但具有不同的created_at时间戳。 该查询旨在从同一session_id中获取至少有一个条目的所有条目,其create_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)

然而,这个黑客对我不起作用,使它更慢。

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

3 个答案:

答案 0 :(得分:6)

根据您的数据分布,请使用此

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_atsession_id上创建两个单独的索引)

答案 1 :(得分:3)

我也遇到了双子查询技巧的问题, 顺便说一下,我发现使用它对我有用(根据你的查询):

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

在我的情况下,原始查询可以使用连接或“正常”双子查询技巧工作数小时,修改后的双子查询需要0秒:)

答案 2 :(得分:1)

怎么样:

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上的索引也可能会有所帮助。