美文网首页
代码CR之分页查询常见问题

代码CR之分页查询常见问题

作者: GuangHui | 来源:发表于2023-01-07 15:33 被阅读0次
    分页查询常见问题:
    • 1.完全没有分页
    • 2.分页size太大
    • 3.超多分页慢SQL
    1.完全没有分页

    反例:

    
    private List<OrderDTO> queryOrderList(Long customerId) {
        if (customerId == null) {
            return Lists.newArrayList();
        }
    
        List<OrderDO> orderDOList = orderMapper.list(customerId);
        return orderConverter.doList2dtoList(orderDOList);
    }
    

    正例:

    private Page<OrderDTO> queryOrderList(OrderPageQuery query) {
        Preconditions.checkNotNull(query, "查询条件不能为空");
        Preconditions.checkArgument(query.getPageSize() <= MAX_PAGE_SIZE, "分页size不能大于" + MAX_PAGE_SIZE);
        // 分页size一般由前端传入
        // query.setPageSize(20);
        long cnt = orderMapper.count(query);
        if (cnt == 0) {
            return PageQueryUtil.buildPageData(query, null, cnt);
        }
        List<OrderDO> orderDOList = orderMapper.list(query);
        List<OrderDTO> orderDTOList = orderConverter.doList2dtoList(orderDOList);
        return PageQueryUtil.buildPageData(query, orderDTOList, cnt);
    }
    

    没有分页的列表查询对 DB 性能影响非常大,特别是在项目初期,因为数据量非常小问题不明显,而导致没有及时发现,会给未来留坑。

    2.分页size太大

    反例:

    
    private Page<OrderDTO> queryOrderList2(OrderPageQuery query) {
        Preconditions.checkNotNull(query, "查询条件不能为空");
        query.setPageSize(10000);
        long cnt = orderMapper.count(query);
        if (cnt == 0) {
            return PageQueryUtil.buildPageData(query, null, cnt);
        }
        List<OrderDO> orderDOList = orderMapper.list(query);
        List<OrderDTO> orderDTOList = orderConverter.doList2dtoList(orderDOList);
        return PageQueryUtil.buildPageData(query, orderDTOList, cnt);
    }
    

    分页 size 的大小并没有一个固定的标准,取决于业务需求、数据量及数据库等,但动辄几千上万的分页 size,会带来性能瓶颈,而大量的慢 SQL 不但影响客户体验,对系统稳定性也是极大的隐患。

    3.超多分页慢SQL

    反例:

    
    <!-- 分页查询订单列表 -->
    <select id="list" parameterType="com.xxx.OrderPageQuery" resultType="com.xxx.OrderDO">
        SELECT
            <include refid="all_columns"/>
        FROM t_order
            <include refid="listConditions"/>
        ORDER BY id DESC
        LIMIT #{offset},#{pageSize}
    </select>
    

    正例:

    
    <!-- 分页查询订单列表 -->
    <select id="list" parameterType="com.xxx.OrderPageQuery" resultType="com.xxx.OrderDO">
        SELECT
            <include refid="all_columns"/>
        FROM t_order a
        INNER JOIN (
            SELECT id AS bid
            FROM t_order
                <include refid="listConditions"/>
            ORDER BY id DESC
            LIMIT #{offset},#{pageSize}
        ) b ON a.id = b.bid
    </select>
    

    以上 bad case 的 SQL 在超多页分页查询时性能极其低下,存在多次回表甚至 Using Filesort 的问题,在阿里巴巴编码规范中也有明确的规避方案,此处不展开。


    相关文章

      网友评论

          本文标题:代码CR之分页查询常见问题

          本文链接:https://www.haomeiwen.com/subject/vamscdtx.html