主流數據庫分頁 SQL
| 數據庫 | 語法 | 示例 (第 2 頁,每頁 10 條) |
| MySQL / PostgreSQL / SQLite |
LIMIT offset, count |
SELECT * FROM t LIMIT 10, 10 |
| Oracle 12c+ |
OFFSET ... ROWS FETCH NEXT ... ROWS ONLY |
SELECT * FROM t OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY |
| SQL Server 2012+ |
OFFSET ... ROWS FETCH NEXT ... ROWS ONLY |
同 Oracle |
| SQL Server 2008/2005 |
ROW_NUMBER() OVER (ORDER BY ...) + 子查詢 |
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) rn FROM t) tmp WHERE rn BETWEEN 11 AND 20 |
| DB2 |
FETCH FIRST ... ROWS ONLY + 子查詢 |
類似 SQL Server 2008 |
Java 代碼實現模式
1. 手寫分頁工具類
public class PageHelper {
public static String buildPageSql(String sql, int pageNum, int pageSize, String dialect) {
switch (dialect) {
case "mysql": return sql + " LIMIT " + (pageNum-1)*pageSize + "," + pageSize;
case "oracle": return "SELECT * FROM (" + sql + ") WHERE rownum ..."; // 略
// ...
}
}
}
2. MyBatis 分頁插件
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.3</version>
</dependency>
// 使用
PageHelper.startPage(2, 10);
List list = userMapper.selectAll(); // 自動拼接 LIMIT
PageInfo page = new PageInfo<>(list); // 獲取總數、總頁數等
3. Spring Data JPA
Pageable pageable = PageRequest.of(1, 10, Sort.by("id").descending());
Page page = userRepository.findAll(pageable);
分頁模式分類
| 模式 | 特點 | 優點 | 缺點 |
| 偏移分頁 | LIMIT/OFFSET | 簡單、支持跳頁 | 深翻頁性能差(掃描前 N 行) |
| 游標/Keyset 分頁 | WHERE id > lastId ORDER BY id LIMIT N | 性能極佳、無深翻頁問題 | 不支持隨機跳頁、需唯一排序鍵 |
| 滾動加載 | 前端無限滾動調用游標分頁 | 用戶體驗好 | 無法 SEO、無法跳頁 |
性能優化建議
- 大數據量(百萬級+)強制使用游標分頁,禁用 OFFSET。
- 覆蓋索引包含 ORDER BY 列,避免回表。
- 總數統計
COUNT(*) 緩存或異步估算。
- 禁止
SELECT *,只查需要的列。
選對分頁模式,性能提升百倍。