我在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)
然而,这个黑客对我不起作用,使它更慢。
有关如何重写此查询的任何想法?
答案 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_at
和session_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_at
和session_id
上的索引也可能会有所帮助。