[英]MySQL: where exists VS where id in [performance]
这个问题在这里也存在: 在Laravel的表现不佳 ...但是没有答案。
那个问题的作者也遇到了类似的情况:
replays
表有4M行 players
表有4000万行 此查询使用where exists
,并且需要大量时间(70s)来完成:
select * from `replays`
where exists (
select * from `players`
where `replays`.`id` = `players`.`replay_id`
and `battletag_name` = 'test')
order by `id` asc
limit 100;
但是当更改为使用where id in
而不是where exists
-更快(0.4s):
select * from `replays`
where id in (
select replay_id from `players`
where `battletag_name` = 'test')
order by `id` asc
limit 100;
正在使用MySQL(InnoDB)。
我想了解为什么where exists
VS与where exists
where id in
之间的性能会有如此大的差异-是因为MySQL的工作方式吗? 我希望“存在”变体会更快,因为MySQL只会检查相关行是否存在...但是我错了(在这种情况下,我可能不理解“存在”是如何工作的)。
您应该显示执行计划。
为了优化exists
,您需要在players(replay_id, battletag_name)
上建立索引。 replays(id)
的索引也应该有帮助-但是如果id
是主键,则已经有一个索引。
戈登有一个很好的答案。 事实是,性能取决于许多不同的因素,包括数据库设计/架构和数据量。
作为粗略的指导, exists
子查询将对replays
每一行执行一次,而in
子查询将执行一次以获取子查询的结果,然后将针对每一行搜索这些结果在replays
。
因此,使用exists
,索引/访问路径越好,它将运行得越快。 如果没有相关的索引,它将只读取所有行,直到找到匹配项。 对于replays
每一行。 对于没有匹配项的行,最终每次都会读取整个players
表。 在找到比赛之前,即使是有比赛的行也可以通读大量players
。
随着in
从子查询,它将运行更快的结果集越小。 对于不匹配的用户,只需快速检查小的子查询行即可找到该答案。 就是说,您没有从索引中受益(如果它能以这种方式工作),因此对于子查询中的大型结果集,它必须先读取子选择中的每一行,然后再确定何时不存在匹配项。
就是说,数据库优化器非常聪明,并且并不总是按照您要求的方式评估查询,因此,为什么要检查执行计划并进行自我测试对于找出最佳方法很重要。 期望某条执行路径只是为了发现优化器根据期望数据的外观选择了不同的执行方法,这并不罕见。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.