liusheng
4 天以前 fb89df539c6293a41933e445df25fa9b8047ba18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
-- =====================================================================
-- 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;