MyBatis-Plus 自定义 COUNT 查询
前言
在使用 MyBatis-Plus 的分页组件进行分页查询时, MyBatis-Plus 会自动帮我们返回总数、当前页、总页数等参数,总数是 MyBatis-Plus 自己使用我们的数据查询 SQL 外面套了一层查询来返回总数,虽然 MyBatis-Plus 官方也说明了这里有优化,但是需要根据标准走,若没有根据标准来或者 SQL 比较复杂等特殊情况,还是无法避免会被直接套在外面导致查询效率低下,我这里的情况是由于原分页查询的逻辑较复杂,原先为两个 OR,后改为两个 UNION ALL,COUNT 查询套在 UNION ALL 查询里,竟然比数据查询耗时都要长,所需需要特殊处理一下 COUNT 查询;
查询优化
本次优化的 COUNT 查询中,摒弃了 MyBatis-Plus 默认套的查询,采用自己写一个新 SQL 的方式来代替,在多次试验中,最终的 SQL 和原查询数据的 SQL 大致相同,还是两次 UNION ALL 来查询,但是字段只返回 COUNT 数量且无需 LEFT JOIN 另一张表,最外层套用一个查询来累加三个 SQL(一个查询两个 UNION ALL)的总数量,最终查询的结果和原默认 SQL 查询出来的结果一致,查询时间由原来的 1.25 秒提升至 0.04 秒。
步骤
- 在对应 Mapper.xml 中写好对应 SQL,定义好 id 字段,查询条件和查询数据的 SQL 条件是一致的,是自己带过来的,无需担心,例如:
1<select id="queryMsgReadFlagCount" resultType="java.lang.Long"> 2 SELECT SUM(num) FROM( 3 SELECT COUNT(*) AS num FROM message AS m 4 WHERE 5 m.user_id = #{request.userId} AND m.enterprise_id = #{request.enterpriseId} 6 <include refid="common_where"/> 7 UNION ALL 8 SELECT COUNT(*) AS num FROM message AS m 9 WHERE 10 m.push_type = 0 11 <include refid="common_where"/> 12 UNION ALL 13 SELECT COUNT(*) AS num FROM message AS m 14 WHERE 15 m.push_type = 1 AND m.enterprise_id = #{request.enterpriseId} 16 <include refid="common_where"/> 17 ) TOTAL 18</select>
- 在 page 查询中定义好 countId 值,传入第一步写好的自定义 COUNT SQL 的 id 值,例如:
1@Override 2public BasePageResponse<MessageResp> listMsg(ListMessageReq request) { 3 Page<MessageResp> page = new Page<>(request.getCurrent(), request.getSize()); 4 page.setCountId("queryMsgReadFlagCount"); 5 IPage<MessageResp> iPage = this.baseMapper.queryMsgReadFlag(page, request); 6 BasePageResponse<MessageResp> response = new BasePageResponse<>(); 7 BeanUtils.copyProperties(iPage, response); 8 response.setRecords(iPage.getRecords()); 9 return response; 10}
标题:MyBatis-Plus 自定义 COUNT 查询
作者:zzzzchen
地址:https://dczzs.com/articles/2023/08/14/1692001501915.html