相关文章推荐

在使用 MyBatis-Plus 的分页组件进行分页查询时, MyBatis-Plus 会自动帮我们返回总数、当前页、总页数等参数,总数是 MyBatis-Plus 自己使用我们的数据查询 SQL 外面套了一层查询来返回总数,虽然 MyBatis-Plus 官方也说明了这里有优化,但是需要根据标准走,若没有根据标准来或者 SQL 比较复杂等特殊情况,还是无法避免会被直接套在外面导致查询效率低下,我这里的情况是由于原分页查询的逻辑较复杂,原先为两个 OR,后改为两个 UNION ALL,COUNT 查询套在 UNION ALL 查询里,竟然比数据查询耗时都要长,所需需要特殊处理一下 COUNT 查询;

官方解释: https://baomidou.com/pages/97710a/#page

本次优化的 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;
    
  •  
    推荐文章