使用左外连接和 OR 子句的慢 MySQL 查询

问题描述 投票:0回答:1

我有以下疑问。

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 使用索引?如何阻止它?

mysql performance left-join
1个回答
0
投票

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

您可以通过将查询拆分为两个查询并将它们联合在一起来避免 OR 引起的 SQL 缓慢部分问题:

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)索引(如果你有它 - 如果你没有添加它)通过首先查看评论表来优化执行。

披露:我写了引用的文章。

© www.soinside.com 2019 - 2024. All rights reserved.