分頁查詢常見問題:
- 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 性能影響非常大鳍怨,特別是在項目初期蒿柳,因為數(shù)據(jù)量非常小問題不明顯,而導(dǎo)致沒有及時發(fā)現(xiàn)岳枷,會給未來留坑芒填。
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 的大小并沒有一個固定的標(biāo)準(zhǔn),取決于業(yè)務(wù)需求空繁、數(shù)據(jù)量及數(shù)據(jù)庫等殿衰,但動輒幾千上萬的分頁 size,會帶來性能瓶頸盛泡,而大量的慢 SQL 不但影響客戶體驗闷祥,對系統(tǒng)穩(wěn)定性也是極大的隱患。
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 的問題凯砍,在阿里巴巴編碼規(guī)范中也有明確的規(guī)避方案,此處不展開拴竹。