DB2 三种分页方案完整版对比(含原理+SQL实现+优缺点+选型)
一、三种分页方式汇总
-
ROW_NUMBER() 行号分页(老版本通用)
-
OFFSET FETCH 偏移分页(DB29.7+标准)
-
Keyset 键集分页/游标分页(大数据最优)
二、完整实现 SQL
- ROW_NUMBER() 分页
-- 通用写法,必须加ORDER BY
SELECT * FROM (
SELECT t.*,ROW_NUMBER() OVER(ORDER BY id DESC) rn
FROM table_name t
) temp
WHERE rn BETWEEN ? AND ?;
参数:起始行、结束行
- OFFSET FETCH 分页(DB2推荐简洁写法)
SELECT * FROM table_name
ORDER BY id DESC
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY;
参数:页码偏移量、每页条数
- Keyset 键集分页(高性能最优)
第一页
SELECT * FROM table_name
ORDER BY create_time DESC,id DESC
FETCH NEXT 10 ROWS ONLY;
下一页(传上一页最后一条:最后时间+最后主键ID)
SELECT * FROM table_name
WHERE create_time < ?
OR (create_time = ? AND id < ?)
ORDER BY create_time DESC,id DESC
FETCH NEXT 10 ROWS ONLY;
三、全方位对比表
对比项 ROW_NUMBER行号分页 OFFSET FETCH偏移分页 Keyset键集分页
支持版本 DB2全版本兼容 DB2 9.7及以上 全版本都支持
实现难度 中等,嵌套多层 极低,尾部追加 中等,前端传锚点值
分页参数 开始行、结束行 pageNum、pageSize 上页最后一条排序字段值
底层原理 全结果集生成行号再过滤 数据库跳过前置行数取数据 利用索引范围定位,直接截取
深分页性能 极差,越往后越慢 差,偏移越大越慢 顶级,深浅分页速度一致
索引利用率 低,易走全表排序 中,大偏移失效 极高,纯索引检索
数据稳定性 易重复、漏数据 易重复、漏数据 几乎无重复无遗漏
能否跳页 支持任意页码跳转 支持任意页码跳转 仅支持上一页/下一页,不支持直达
内存消耗 高,生成临时行号集 中 极低
业务适配 老项目兼容、小数据 中小型列表、后台管理 大数据列表、APP/前端信息流
排序要求 必须指定OVER内排序 必须整体ORDER BY 必须带唯一主键联合排序
四、各自优缺点
- ROW_NUMBER 分页
优点
• 兼容DB28、9等老旧版本,无版本限制
• 逻辑通用,跨库改动小
缺点
• 大数据量必慢,全量生成行号开销极大
• 多层嵌套SQL臃肿,可读性差
• 深分页性能断崖下跌
- OFFSET FETCH 分页
优点
• SQL极简,代码整洁易维护
• 前几页分页速度快
• 原生语法,优化器原生支持
缺点
• 偏移量越大性能越差
• 百万级数据分页基本不可用
• 并发增删易出现数据错乱
- Keyset 键集分页
优点
• 百万/千万级数据分页性能无敌
• 不受页码深浅影响,速度恒定
• 占用资源最少,数据库压力最小
• 分页数据最稳定
缺点
• 不支持直接跳转到指定页码
• 前端需要额外存储上一页末尾锚点值
• 多字段排序条件书写略繁琐
五、业务选型最终建议
- 老旧DB2环境(9.7以下)
只能用:ROW_NUMBER 分页
- 后台管理系统、数据量小、需要跳页
优先:OFFSET FETCH 分页
- APP列表、日志、订单、大数据流、千万级表
强制用:Keyset 键集分页
- 混合最优方案
前100页用OFFSET,100页后切换键集分页,兼顾体验与性能
六、DB2分页通用强制规范(三种都要遵守)
-
所有分页必须带ORDER BY,否则分页结果随机错乱
-
排序字段建立单列/复合索引,无索引所有分页全废
-
禁止SELECT *,只查业务所需字段,大幅提速
-
大表严禁使用深偏移分页,优先键集分页