如何减少这个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查询执行时间的主要内容,如果未能解决你的问题,请参考以下文章

如何减少此脚本的执行时间?

减少 Hive 查询执行时间的方法

如何减少查询执行时间 vb.net webform

如何减少简单选择查询的响应时间?

MySQL中如何查看“慢查询”,如何分析执行SQL的效率?

如何检查先前的查询是不是正确执行?