如何减少这个mysql查询执行时间
Posted
技术标签:
【中文标题】如何减少这个mysql查询执行时间【英文标题】:How to decrease this mysql query execution time 【发布时间】:2020-01-23 13:40:35 【问题描述】:这是我的 mysql 查询:
select en.course_instance_id, count(*)
from user u
inner join enrollment en on en.user_id = u.user_id
where en.account_id=5392
and en.course_instance_id in (5127039, 5127040)
and enrollment_state='ACTIVE'
and u.state!='DELETED'
group by en.course_instance_id;
我的user
表有user_id
作为主键,enrollment
表有(user_id, course_id)
作为主键。
基本上,此查询试图查找在每个 course_instance 中注册的用户数。
现在,course_instance_id
5127039 注册了 352438 个用户,course_instance_id
5127040 注册了 1 个用户。
当我尝试运行此查询时,它会超时(需要超过 2 分钟)。
我已经检查了两个表的索引,我假设它们使用正确。对于enrollment
,使用course_instance_id, course_id
的表索引,对于user
,使用表PRIMARY 索引,即user_id
。
已附上用于此查询的索引的快照:
【问题讨论】:
执行desc analyze select...
查看成本结构dev.mysql.com/doc/refman/8.0/en/explain.html
【参考方案1】:
对于这个查询:
select en.course_instance_id, count(*)
from user u inner join
enrollment en
on en.user_id = u.user_id
where en.account_id = 5392 and
en.course_instance_id in (5127039, 5127040) and
en.enrollment_state = 'ACTIVE' and
u.state <> 'DELETED'
group by en.course_instance_id;
我会推荐一个关于enrollment(account_id, enrollment_state, course_instance_id, user_id)
的索引。
您可以在users(user_id, state)
上添加索引,但鉴于user_id
可能是主键,这并不是真正需要的。
【讨论】:
谢谢。该索引有助于大大减少执行时间。【参考方案2】:从概念上讲,我认为您的查询会更清晰。输出应该是相同的,但 mysql 可能对 join 子句对用户的所有限制更满意。我不确定enrollment_state 来自哪个表。
select en.course_instance_id, count(*)
from enrollment en
inner join user u on en.user_id = u.user_id and u.state!='DELETED'
where en.account_id=5392
and en.course_instance_id in (5127039, 5127040)
and enrollment_state='ACTIVE'
group by en.course_instance_id;
【讨论】:
。 . . MySQL 是不会体验诸如幸福之类的情绪的软件(幸灾乐祸可能是另一回事;)。也就是说,在on
子句和where
子句中过滤内连接应该没有区别。
经过几次测试,我得出了同样的结论。我认为从注册加入到用户中选择更清晰,因为查询实际上是从注册中选择而不是从用户中选择,但这是与性能改进不同的问题。
...,至少不适用于INNER JOIN
。 (LEFT
/RIGHT
可能很重要。)以上是关于如何减少这个mysql查询执行时间的主要内容,如果未能解决你的问题,请参考以下文章