select *
from `attendance_marks`
where exists (select *
from `attendables`
where `attendance_marks`.`attendable_id` = `attendables`.`id`
and `attendable_type` = 'student'
and `attendable_id` = 258672
and `attendables`.`deleted_at` is null
)
and (`marked_at` between '2022-09-01 00:00:00' and '2022-09-30 23:59:59')这个查询花费的时间太长,大约7-10秒。我正试图优化它,但我仍然停留在这里。
Attendance_marks指数

托管索引

请帮我优化一下。
供参考
可访问的行数= 80966
行数attendance_marks = 1853696
解释选择

发布于 2022-09-20 08:00:19
我认为如果我们使用JOINS而不是Sub-Query,那么它就会更有表现力。不幸的是,我没有准确的数据来测试性能。
select *
from attendance_marks
inner join attendables on attendables.id = attendance_marks.attendable_id
where attendable_type = 'student'
and attendable_id = 258672
and attendables.deleted_at is null
and (marked_at between '2022-09-01 00:00:00' and '2022-09-30 23:59:59')我不确定您的业务需求是否允许更改PK并添加索引。如果是这样的话:
attendable_id.
attendables.id是PK。如果不是,请向其添加一个索引。或者最好让它成为PK.attendable_type有很多不同的值。然后考虑在那里添加一个索引。如果可能的话,marked_at中的秒字段之前不具有粒度,而是转到最近的分钟。在我们的例子中,我们可以将2022-10-01 00:00:00.与2022-09-30 23:59:59相加。
发布于 2022-09-22 00:56:07
select b.*
from `attendance_marks` AS am
JOIN `attendables` AS b ON am.`attendable_id` = b.`id`
WHERE b.`attendable_type` = 'student'
and b.`attendable_id` = 258672
and b.`deleted_at` is null
AND am.`marked_at` >= '2022-09-01'
AND am.`marked_at` < '2022-09-01 + INTERVAL 1 MONTH 还有这些
am: INDEX(marked_at, attendable_id)
am: INDEX(attendable_id, marked_at)
b: INDEX(attendable_type, attendable_id, attendables)注意,日期时间范围适用于任何粒度。
(请务必检查我是否得到了正确表的别名。)
使用这些索引,这个公式应该允许优化器首先选择哪个表更有效。
https://stackoverflow.com/questions/73783184
复制相似问题