查询性能优化求助:单条结果耗时6.18分钟如何改进?
查询性能优化方案
首先看执行计划的核心问题:查询从user_tasks(ut)开始全表扫描(type: ALL),扫描了1.29亿行,但已知exception_type = 1的记录仅3条,这是性能瓶颈的根源——优化器错误地选择了从大表开始扫描,而非先过滤出极小的结果集再关联其他表。
以下是具体优化步骤:
1. 给user_tasks添加精准索引
针对exception_type = 1的过滤条件,创建一个能直接定位目标记录且覆盖连接字段的索引:
CREATE INDEX idx_exception_type_id ON user_tasks (exception_type, id);
这个索引会让数据库直接快速找到所有exception_type=1的3条记录,无需扫描全表,大幅减少初始数据量。
2. 引导优化器选择更优的连接顺序
如果添加索引后优化器仍未自动调整执行顺序,可以强制指定从过滤条件更严格的表开始查询,比如调整查询逻辑先从user_tasks的小结果集关联:
SELECT COUNT(1) AS rage_tap FROM user_tasks ut JOIN user_tasks_metadata utm ON ut.id = utm.user_task_id JOIN summary_funnel_1066 s ON utm.asi = s.asi WHERE ut.exception_type = 1 AND s.seq_no = 1 AND s.created_at BETWEEN '2022-09-27 00:00:00' AND '2022-10-27 00:00:00';
调整后的逻辑会先拿到仅3条的ut记录,再关联utm和s,数据量骤减,耗时会大幅降低。也可以用STRAIGHT_JOIN强制指定连接顺序:
SELECT COUNT(1) AS rage_tap FROM summary_funnel_1066 s STRAIGHT_JOIN user_tasks_metadata utm ON utm.asi = s.asi STRAIGHT_JOIN user_tasks ut ON ut.id = utm.user_task_id WHERE s.seq_no = 1 AND s.created_at BETWEEN '2022-09-27 00:00:00' AND '2022-10-27 00:00:00' AND ut.exception_type = 1;
3. 验证summary_funnel_1066的索引有效性
当前查询用到了unique_asi_seq_no索引(asi, seq_no),配合s.seq_no=1的条件能快速定位记录。如果想进一步优化,可以尝试使用seq_no_date索引(seq_no, created_at),它能先过滤出符合时间范围的s记录,再关联utm,减少后续连接的数据量:
SELECT COUNT(1) AS rage_tap FROM summary_funnel_1066 s FORCE INDEX (seq_no_date) JOIN user_tasks_metadata utm ON utm.asi = s.asi JOIN user_tasks ut ON ut.id = utm.user_task_id WHERE s.seq_no = 1 AND s.created_at BETWEEN '2022-09-27 00:00:00' AND '2022-10-27 00:00:00' AND ut.exception_type = 1;
4. 确认user_tasks_metadata的索引覆盖
当前查询用到了usertask_fk_idx(user_task_id),换成id_asi索引(user_task_id, asi)可以直接从索引中拿到asi字段,无需回表查询utm的主键数据,进一步提升连接效率:
SELECT COUNT(1) AS rage_tap FROM summary_funnel_1066 s JOIN user_tasks_metadata utm FORCE INDEX (id_asi) ON utm.asi = s.asi JOIN user_tasks ut ON ut.id = utm.user_task_id WHERE s.seq_no = 1 AND s.created_at BETWEEN '2022-09-27 00:00:00' AND '2022-10-27 00:00:00' AND ut.exception_type = 1;
内容的提问来源于stack exchange,提问作者RRQ
相关产品推荐
相关产品推荐

