在 MySql 中的 WHERE 语句上使用 OR 会导致执行缓慢
Posted
技术标签:
【中文标题】在 MySql 中的 WHERE 语句上使用 OR 会导致执行缓慢【英文标题】:Using OR on WHERE statement in MySql causes slow excecution 【发布时间】:2016-10-11 09:05:37 【问题描述】:与使用两个单独的查询实现相同的查询相比,以下查询的执行时间几乎是 mysql 的 7 倍,并且避免了 WHERE 语句上的 OR。我更喜欢使用单个查询,因为我可以对所有内容进行排序和分组。
这是有问题的查询:
EXPLAIN SELECT *
FROM `posts`
LEFT JOIN `teams_users`
ON (teams_users.team_id=posts.team_id
AND teams_users.user_id='7135')
WHERE (teams_users.status='1'
OR posts.user_id='7135');
结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE posts ALL user_id NULL NULL NULL 169642
1 SIMPLE teams_users eq_ref PRIMARY PRIMARY 8 posts.team_id,const 1 Using where
现在,如果我改为执行以下两个查询,则总执行时间将缩短 7 倍:
EXPLAIN SELECT *
FROM `posts`
LEFT JOIN `teams_users`
ON (teams_users.team_id=posts.team_id
AND teams_users.user_id='7135')
WHERE (teams_users.status='1');
结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE teams_users ref PRIMARY,status status 1 const 5822 Using where
1 SIMPLE posts ref team_id team_id 5 teams_users.team_id 9 Using where
和:
EXPLAIN SELECT *
FROM `posts`
LEFT JOIN `teams_users`
ON (teams_users.team_id=posts.team_id
AND teams_users.user_id='7135')
WHERE (posts.user_id='7135');
结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE posts ref user_id user_id 4 const 142
1 SIMPLE teams_users eq_ref PRIMARY PRIMARY 8 posts.team_id,const 1
显然,这两个查询的扫描行数要少得多。 为什么初始查询很慢? 谢谢。
【问题讨论】:
【参考方案1】:是的,OR
经常是性能杀手。一个常见的解决方法是使用UNION
。以您为例:
SELECT *
FROM `posts`
LEFT JOIN `teams_users`
ON (teams_users.team_id=posts.team_id
AND teams_users.user_id='7135')
WHERE (teams_users.status='1')
UNION DISTINCT
SELECT *
FROM `posts`
LEFT JOIN `teams_users`
ON (teams_users.team_id=posts.team_id
AND teams_users.user_id='7135')
WHERE (posts.user_id='7135');
如果您确定没有重复,请更改为更快的UNION ALL
。
如果您不是在寻找缺少的team_users
行,请使用JOIN
而不是LEFT JOIN
。
如果您需要ORDER BY
,请添加一些括号:
( SELECT ... )
UNION ...
( SELECT ... )
ORDER BY ...
否则,ORDER BY
将仅适用于第二个SELECT
。 (如果您还需要“分页”,请参阅my blog。)
请注意,在某些情况下您可能还需要LIMIT
。
【讨论】:
谢谢。事实上,UNION 比在 When 语句上使用 OR 快得多。【参考方案2】:没有OR
子句的查询都是sargable. That is, they both can be satisfied using indexes。
如果 MySQL 查询计划器包含逻辑以计算出它可以将其重写为两个查询的 UNION ALL
,那么带有 OR
的查询将是 sargable。 MySQL 查询计划器(还)没有这种逻辑。
因此,它会进行表扫描以获取结果集。这些通常非常缓慢。
【讨论】:
以上是关于在 MySql 中的 WHERE 语句上使用 OR 会导致执行缓慢的主要内容,如果未能解决你的问题,请参考以下文章