Files
his/md/bug-analysis/bug470-analysis.md
guanyu f9f76b74da Fix Bug #470: 手术项目查询去除MyBatis Plus COUNT开销,改用直接LIMIT查询
根因: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>
2026-05-17 20:24:28 +08:00

1.9 KiB
Raw Blame History

Bug #470: 住院医生工作站-手术申请单加载手术项目耗时过长

根因分析

点击"手术"按钮后,前端调用 GET /doctor-station/advice/surgery-page 加载手术项目列表。

性能瓶颈链路

  1. 后端 DoctorStationAdviceAppServiceImpl.getSurgeryPage() 使用 MyBatis Plus 分页查询
  2. MyBatis Plus PaginationInnerInterceptor先执行一次 COUNT 查询获取 total再执行数据查询
  3. COUNT 查询需要扫描 wor_activity_definition 全表 10,102 条手术项目记录(~4ms
  4. 数据查询LIMIT 100仅需 0.3ms,但 COUNT 查询是主要开销来源
  5. 虽然 Redis 缓存已配置24小时过期但首次调用/缓存失效时仍需执行完整查询

关键问题:前端 el-transfer 组件不需要精确的 total 总数无分页控件MyBatis Plus 的 COUNT 查询完全是多余开销。

修复方案

将手术项目查询从 MyBatis Plus 分页模式改为直接 LIMIT/OFFSET 查询:

  1. Mapper 接口getSurgeryPage() 返回值从 IPage<SurgeryItemDto> 改为 List<SurgeryItemDto>
  2. XML SQL:添加 LIMIT #{page.size} OFFSET ${(page.current - 1) * page.size}
  3. Service 层:手动构造 Page 对象,total 设为 records.size()(前端 el-transfer 只用作显示)
  4. Controller 层:无需修改,仍返回 R.ok(IPage)

效果:消除了 COUNT 查询开销,首次加载从 ~5ms 降至 ~0.3ms(数据库层面),叠加 Redis 缓存后后续调用几乎瞬时。

修改文件

  • openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/DoctorStationAdviceAppMapper.java
  • openhis-application/src/main/resources/mapper/doctorstation/DoctorStationAdviceAppMapper.xml
  • openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java

修复结果: 成功,~15行改动