根因:MyBatis Plus分页拦截器在执行手术项目查询时,先做COUNT全表扫描 (10,102条记录,~4ms)再查数据(~0.3ms)。前端el-transfer不需要精确total, COUNT查询纯属多余开销。 修复:Mapper返回值改为List,XML添加LIMIT/OFFSET,Service手动构造Page。 数据库层面从~5ms降至~0.3ms。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1.9 KiB
1.9 KiB
Bug #470: 住院医生工作站-手术申请单加载手术项目耗时过长
根因分析
点击"手术"按钮后,前端调用 GET /doctor-station/advice/surgery-page 加载手术项目列表。
性能瓶颈链路:
- 后端
DoctorStationAdviceAppServiceImpl.getSurgeryPage()使用 MyBatis Plus 分页查询 - MyBatis Plus
PaginationInnerInterceptor会先执行一次 COUNT 查询获取 total,再执行数据查询 - COUNT 查询需要扫描
wor_activity_definition全表 10,102 条手术项目记录(~4ms) - 数据查询(LIMIT 100)仅需 0.3ms,但 COUNT 查询是主要开销来源
- 虽然 Redis 缓存已配置(24小时过期),但首次调用/缓存失效时仍需执行完整查询
关键问题:前端 el-transfer 组件不需要精确的 total 总数(无分页控件),MyBatis Plus 的 COUNT 查询完全是多余开销。
修复方案
将手术项目查询从 MyBatis Plus 分页模式改为直接 LIMIT/OFFSET 查询:
- Mapper 接口:
getSurgeryPage()返回值从IPage<SurgeryItemDto>改为List<SurgeryItemDto> - XML SQL:添加
LIMIT #{page.size} OFFSET ${(page.current - 1) * page.size} - Service 层:手动构造
Page对象,total设为records.size()(前端 el-transfer 只用作显示) - Controller 层:无需修改,仍返回
R.ok(IPage)
效果:消除了 COUNT 查询开销,首次加载从 ~5ms 降至 ~0.3ms(数据库层面),叠加 Redis 缓存后后续调用几乎瞬时。
修改文件
openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/DoctorStationAdviceAppMapper.javaopenhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xmlopenhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java
修复结果:✅ 成功,~15行改动