分頁查詢需同時返回List<Data>和totalCount。單條SQL用COUNT(*) OVER()或子查詢導致計劃複雜、執行慢;應用層list.size()需先全量加載,內存壓力大。
-- 1. 獲取分頁數據(利用索引、Limit/Offset)
SELECT id, name, ...
FROM large_table
WHERE conditions
ORDER BY create_time DESC
LIMIT 20 OFFSET 0;
-- 2. 獲取總數(可只掃描索引、並行執行)
SELECT COUNT(1)
FROM large_table
WHERE conditions;
CompletableFuture並行發起,總耗時≈max(查數據, 查總數)。COUNT結果(TTL 1-5分鐘),極大降低DB壓力。COUNT查詢建立INDEX(conditions_columns)實現Index Only Scan。EXPLAIN SELECT ...的rows估算值,或information_schema.TABLES.TABLE_ROWS(誤差±20%)。OFFSET,用WHERE id > last_id ORDER BY id LIMIT 20避免深分頁掃描。public PageResult queryPage(QueryParam param) {
// 並行執行
CompletableFuture> dataFuture = CompletableFuture.supplyAsync(() ->
dao.selectPage(param), executor);
CompletableFuture countFuture = CompletableFuture.supplyAsync(() ->
dao.countTotal(param), executor);
List data = dataFuture.join();
Long total = countFuture.join();
return new PageResult<>(data, total, param.getPageNo(), param.getPageSize());
}
WHERE條件**必須完全一致**,否則總數與數據不對應。SQL_CALC_FOUND_ROWS + FOUND_ROWS()已棄用(8.0移除),不推薦使用。