-- ===================================================================== -- service_subtask 索引优化脚本 -- 目标接口:POST /smartor/serviceSubtask/patItem(及共用同一套 SQL 的 /patItemCount、/patItemExport) -- -- 涉及的两条 SQL(都在 ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml): -- 1) id = selectServiceSubtaskList —— 列表,约 100 列 + order by + limit offset -- 2) id = countByCondition —— 同一套 where 的 SUM 聚合(Redis 未命中时执行) -- -- 兼容性:MySQL 5.7 / 8.0 均可执行。 -- * 5.7 不支持降序索引,但 ASC 索引可被反向扫描,order by ... desc 同样能用,无需额外处理; -- * 5.7 没有 EXPLAIN ANALYZE,验证用文末的 EXPLAIN + Handler 状态变量。 -- ===================================================================== -- --------------------------------------------------------------------- -- 0. 执行前先看现状(避免重复建索引 / 确认数据量与列类型) -- --------------------------------------------------------------------- SHOW INDEX FROM service_subtask; SELECT COUNT(*) AS total_rows FROM service_subtask; SELECT COLUMN_NAME, COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'service_subtask' AND COLUMN_NAME IN ('orgid', 'campusid', 'del_flag', 'endtime', 'visit_time', 'sendstate', 'taskid', 'create_time', 'patid', 'inhospid', 'schedule_id', 'loop_count'); -- --------------------------------------------------------------------- -- 1. 必加:列表主查询 / 聚合的公共前缀 + 排序 -- -- where 固定是 del_flag = 0 AND orgid = ? AND campusid = ?(Controller 强制注入) -- order by 默认是 endtime asc/desc -- → 命中后 order by 不再 filesort,且 limit 可以提前截断; -- 同时让 countByCondition 从「全表扫描」降为「一个机构+院区的范围扫描」。 -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_org_cam_del_endtime (orgid, campusid, del_flag, endtime), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 2. 必加:按随访时间排序/筛选(sort=2/3/7/8,以及 startSendDateTime/endSendDateTime 区间) -- 注:这两个区间条件已由 date_format(...) 改写为可走索引的范围比较。 -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_org_cam_del_vtime (orgid, campusid, del_flag, visit_time), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 3. 必加:状态页签(sendstateView → sendstate IN (1,2,3,5,7) / (6) / (4)) -- 用户最常点的就是「待随访 / 已完成 / 无需随访」三个 tab。 -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_org_cam_del_state_end (orgid, campusid, del_flag, sendstate, endtime), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 4. 建议:任务维度下钻(taskid 是这张表最高频的等值条件) -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_org_cam_del_task (orgid, campusid, del_flag, taskid), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 5. 建议:create_time 区间 -- 供 selectServiceSubtaskListByCreateTime / selectServiceSubtaskListAgain 使用。 -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_org_cam_del_ctime (orgid, campusid, del_flag, create_time), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 6. 建议:患者 / 住院记录反查(患者端、再次随访、转科链路) -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_patid (patid), ALGORITHM = INPLACE, LOCK = NONE; ALTER TABLE service_subtask ADD INDEX idx_ss_inhospid (inhospid), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 7. 建议:任务组滚动调度(countActiveByScheduleIdAndLoop,跑得非常勤) -- --------------------------------------------------------------------- ALTER TABLE service_subtask ADD INDEX idx_ss_sched_loop (schedule_id, loop_count), ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 8. 可选:让 countByCondition 变成覆盖索引(索引内完成聚合,不回表) -- 只有当 Redis 命中率低、统计接口仍然慢时才加。 -- 代价:service_subtask 写入频繁,多一个宽索引会加大写入开销。 -- --------------------------------------------------------------------- -- ALTER TABLE service_subtask -- ADD INDEX idx_ss_org_cam_del_state_excep (orgid, campusid, del_flag, sendstate, excep), -- ALGORITHM = INPLACE, LOCK = NONE; -- --------------------------------------------------------------------- -- 9. 收尾:更新统计信息,让优化器立刻用上新索引 -- --------------------------------------------------------------------- ANALYZE TABLE service_subtask; -- ===================================================================== -- 验证(MySQL 5.7 可用) -- ===================================================================== -- 9.1 列表主查询:期望 key = idx_ss_org_cam_del_endtime,Extra 里【没有】Using filesort EXPLAIN SELECT id, endtime FROM service_subtask WHERE del_flag = 0 AND orgid = '这里换成真实 orgid' AND campusid = '这里换成真实 campusid' ORDER BY endtime DESC LIMIT 20 OFFSET 0; -- 9.2 状态页签:期望 key = idx_ss_org_cam_del_state_end EXPLAIN SELECT id, endtime FROM service_subtask WHERE del_flag = 0 AND orgid = '这里换成真实 orgid' AND campusid = '这里换成真实 campusid' AND sendstate IN (1, 2, 3, 5, 7) ORDER BY endtime DESC LIMIT 20 OFFSET 0; -- 9.3 实际扫描量对比(执行前后各跑一次,看 Handler_read_next 是否大幅下降) FLUSH STATUS; SELECT COUNT(1) FROM service_subtask WHERE del_flag = 0 AND orgid = '这里换成真实 orgid' AND campusid = '这里换成真实 campusid'; SHOW SESSION STATUS LIKE 'Handler_read%'; -- ===================================================================== -- 回滚 -- ===================================================================== -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_endtime; -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_vtime; -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_state_end; -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_task; -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_ctime; -- ALTER TABLE service_subtask DROP INDEX idx_ss_patid; -- ALTER TABLE service_subtask DROP INDEX idx_ss_inhospid; -- ALTER TABLE service_subtask DROP INDEX idx_ss_sched_loop; -- ALTER TABLE service_subtask DROP INDEX idx_ss_org_cam_del_state_excep;