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>
This commit is contained in:
@@ -2458,6 +2458,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
|
||||
/**
|
||||
* 手术项目专用分页查询(仅手术 + 定价,无库存/草稿库存/取药科室等无关逻辑)
|
||||
* 使用直接 LIMIT 查询替代 MyBatis Plus 分页,避免 COUNT 全表扫描开销
|
||||
*/
|
||||
@Override
|
||||
public IPage<SurgeryItemDto> getSurgeryPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey) {
|
||||
@@ -2478,15 +2479,21 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
}
|
||||
}
|
||||
|
||||
IPage<SurgeryItemDto> result = doctorStationAdviceAppMapper.getSurgeryPage(
|
||||
// 使用直接 LIMIT 查询,不触发 MyBatis Plus 的 COUNT 开销
|
||||
List<SurgeryItemDto> records = doctorStationAdviceAppMapper.getSurgeryPage(
|
||||
new Page<>(pageNo, pageSize),
|
||||
PublicationStatus.ACTIVE.getValue(),
|
||||
organizationId,
|
||||
searchKey);
|
||||
|
||||
// 手动构造 Page 对象,total 设为 records.size()(前端 el-transfer 不需要精确的 total 总数)
|
||||
IPage<SurgeryItemDto> result = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageNo, pageSize);
|
||||
result.setRecords(records);
|
||||
result.setTotal(records.size());
|
||||
log.info("getSurgeryPage 完成: {}ms, total={}, records={}", System.currentTimeMillis() - start, result.getTotal(), result.getRecords().size());
|
||||
|
||||
// 无搜索时将结果写入缓存
|
||||
if (useCache && result instanceof com.baomidou.mybatisplus.extension.plugins.pagination.Page) {
|
||||
if (useCache) {
|
||||
redisCache.setCacheObject(cacheKey, result, (int) CACHE_EXPIRE_HOURS, java.util.concurrent.TimeUnit.HOURS);
|
||||
log.info("缓存手术项目, key: {}, 过期时间: {} 小时", cacheKey, CACHE_EXPIRE_HOURS);
|
||||
}
|
||||
|
||||
@@ -187,14 +187,15 @@ public interface DoctorStationAdviceAppMapper {
|
||||
|
||||
/**
|
||||
* 手术项目专用分页查询(仅手术 + 定价,无库存/草稿库存/取药科室等无关逻辑)
|
||||
* 使用 LIMIT/OFFSET 直接查询,不执行 COUNT 以提升性能
|
||||
*
|
||||
* @param page 分页参数
|
||||
* @param page 分页参数(仅取 pageNo/pageSize,不触发 MyBatis Plus COUNT)
|
||||
* @param statusEnum 启用状态
|
||||
* @param organizationId 科室ID(可选,用于过滤已配置的手术项目)
|
||||
* @param searchKey 模糊查询关键字(可选)
|
||||
* @return 手术项目分页数据
|
||||
*/
|
||||
IPage<SurgeryItemDto> getSurgeryPage(@Param("page") Page<SurgeryItemDto> page,
|
||||
List<SurgeryItemDto> getSurgeryPage(@Param("page") Page<SurgeryItemDto> page,
|
||||
@Param("statusEnum") Integer statusEnum,
|
||||
@Param("organizationId") Long organizationId,
|
||||
@Param("searchKey") String searchKey);
|
||||
|
||||
@@ -893,6 +893,7 @@
|
||||
AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%')
|
||||
</if>
|
||||
ORDER BY t1.ID, t1.name ASC, t2.ID ASC
|
||||
LIMIT #{page.size} OFFSET ${(page.current - 1) * page.size}
|
||||
</select>
|
||||
|
||||
<!-- 检查项目专用分页查询:仅查检查(23) + 定价,无库存/草稿库存/取药科室等无关逻辑 -->
|
||||
|
||||
Reference in New Issue
Block a user