代碼CR之分頁查詢常見問題

分頁查詢常見問題:
  • 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 的問題,在阿里巴巴編碼規範中也有明確的規避方案,此處不展開。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章