我有以下查询。
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_user
和comments.video_id
上有索引。但是,mysql在视频表上进行全表扫描,这需要花费很多时间。使用UNION
代替LEFT OUTER JOIN
会使其更快但不是选项,因为查询是由django ORM生成的。
为什么OR
子句和LEFT OUTER JOIN
的组合阻止mysql使用索引,我该如何防止它?
答案 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)索引(如果有的话 - 如果不添加)的索引,通过首先查看评论表来优化执行。