使用左外连接和OR子句进行慢速mysql查询

时间:2014-02-07 20:53:47

标签: mysql performance left-join

我有以下查询。

SELECT * FROM video LEFT OUTER JOIN comments ON (video.id = comments.video_id)
WHERE comments.posted_by_user = 1234 OR video.id in (1, 2, 3, 4)

我在video.id comments.posted_by_usercomments.video_id上有索引。但是,mysql在视频表上进行全表扫描,这需要花费很多时间。使用UNION代替LEFT OUTER JOIN会使其更快但不是选项,因为查询是由django ORM生成的。

为什么OR子句和LEFT OUTER JOIN的组合阻止mysql使用索引,我该如何防止它?

1 个答案:

答案 0 :(得分:0)

拖慢速度的并不是两者的结合 - 您所要求的只能通过对视频表进行全表扫描来实现。无论评论表中是否有匹配的行,您都在要求视频表中的所有行。

您可以通过将查询拆分为两个查询并将它们联合在一起来avoid the OR-induced part of SQL slowness 发出:

SELECT *
FROM video
LEFT JOIN comments ON (video.id = comments.video_id)
WHERE video.id IN (1, 2, 3, 4)
UNION
SELECT *
FROM video
LEFT JOIN comments ON (video.id = comments.video_id)
WHERE comments.posted_by_user = 1234;

第一部分执行起来会很快,因为您只从具有 video.id IN (1,2,3,4) 的视频表中获取行,并且可能对 video.id 进行了索引。

第二部分可以利用评论(posted_by_user, video_id)索引(如果有的话 - 如果不添加)的索引,通过首先查看评论表来优化执行。