千家信息网

使用Seek method做分页时offset predicate的注意事项

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,Seek method pagination是最近流行的分页概念。其核心思想是:不再依赖index作为偏移量,而是使用条件表达式作为分页的依据。具体原理我在这里就不再废话了,感兴趣的朋友可以去搜一搜。
千家信息网最后更新 2026年10月31日使用Seek method做分页时offset predicate的注意事项

Seek method pagination是最近流行的分页概念。其核心思想是:不再依赖index作为偏移量,而是使用条件表达式作为分页的依据。具体原理我在这里就不再废话了,感兴趣的朋友可以去搜一搜。

由于"条件表达式"成为了分页依据,那么如何准备分页条件表达式(seek predicate)就成为了关键。

首先,使用seek method pagination的前提条件是:必须是有序结果集。对应于SQL script即需要有order by子句。

下面就是组织seek predicate时需要注意的问题了:

1、order by的列(或多个列)中必须有一个包含全表唯一值的列(就是类似主键那样的列,列中的值必须not null而且unique)。主键列就符合这一特征。

2、order by中出现的列,也必须出现在where子句中,而且排列顺序不能错。比如,order by A asc, B asc, C asc,那么where ... and (A, B, C) > (x, y, z)。where中可以出现其他与seek predicate无关的其他predicate,但要保证order by中出现的column都要出现在where子句中;

3、order by的列必须是同向的,不可以order by A asc, B desc, C asc;

4、(A, B, C, ...) > (x, y, z, ...) 的逻辑运算符必须与order by中的方向对应起来。规则:

翻页方向
order by方向
where中的seek predicate操作符
下一页
ASC
>
DESC
<
上一页
ASC
<
DESC
>

如果你的结果集顺序是ASC,那么,如果你想翻到下一页,你的seek predicate应该用>作为逻辑操作符;如果你想翻到上一页,seek predicate的操作符应该是<。

如果你的结果集顺序是DESC,那么,如果你想翻到下一页,seek predicate的操作符应该是<,反之,用>号。


Note1:

这里需要注意一件事情,就是null值问题。之前说过,order by中至少要有一列为not null unique,而order by中的其他列则没有这个要求,列值可以为null,可以出现重复值。如果翻页时,游标正好指在当前页的最后一行,且这一行中的order by的某个列包含null值,那么就不能用>或<号来拼where条件子句了,要用is null 和 is not null.


现在where中的A、B、C、...都有了,那么每次翻页时,如何找到对应的x,y,z呢?

首先,第一屏。第一屏需要一个batch size(假设为30),也就是每屏加载多少数据。由于第一屏你不知道具体的x,y,z值,所以直接从"头"读取30条记录。获得这30条记录后,紧接着,把第30条记录的A、B、C的值分别记下来,作为x, y, z(假设第一批30条记录的最后一条记录的A='Yan' B='Male' C=1200。下一批30条数据的where子句中的seek predicate就应该为:

select ...from ...where ... and (A, B, C) > ('Yan', 'Male', 1200)order by A, B, Climit 30;

执行上面的SQL会得到下面一页30条记录(如果有30条的话),然后重复刚才采集条件值的操作,例如,第二屏30条记录的最后一条记录的A='Ye' B='Male' C=335。将获得的新的x、y、z值重新拼成第三屏的SQL:

select ...from ...where ... and (A, B, C) > ('Ye', 'Male', 335)order by A, B, Climit 30;

执行上面的SQL会得到下面一页30条记录(如果有30条的话)。如此往复,一直到数据全部加载完毕。

(A, B, C) > ('Ye', 'Male', 335)

这个东西是seek predicate,可以理解为condition offset。传统分页方式用的是index offset。传统分页方式下,你需要知道一共有多少条记录,每屏显示多少条(batch size),然后查询出整个结果集(DBMS的缓存里), 然后使用index offset偏移量skim offset行记录后,开始读取batch条记录。全集查询和skim的过程是很要命的。随着你翻页越往后,比如1000页以后,skim速度就会越慢,内存开销也会越大,数据库负担越重。

但是seek method分页则不同,数据库并不需要查询出所有符合条件的数据,他只需要按照你的condition定位到符合condition的第一条记录,然后往后读取batch size条记录,就完成了那个页面的读取。

目前很多数据库都支持seek predicate的这种(A, B, C) op (x, y, z)写法,而JPA还不支持。但是,我们可以根据所学的数学知识,将不等式变换一下方式,换成等效公式。

  • (A, B) > (x, y) = A>x OR (A=x AND B>y)

  • (A, B, C) > (x, y, z) = A>x OR (A=x AND (B>y OR (B=y AND C>z)))

以此类推,你可以写个递归来自动分解拼装(A, B, C, ...) > (x, y, z, ...)


Tips:

如果遇到order by的列值存在null值,那么,A>null OR (A=null AND B>y)。这种写法在postgresql v9.4中是支持的。如果你的数据库不支持,可以将>null写成A is not null OR (A is null AND B>y)



数据 条件 子句 操作符 数据库 结果 支持 就是 方向 方式 表达式 顺序 查询 一行 传统 写法 逻辑 问题 面的 上一 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 手磨咖啡 广州紫鲸互联网科技有限公司 A股互联网金融科技公司 科技与互联网 互联网电商科技 互联网科技卖菜 北京互联网科技有限公司 青岛互联网科技公司 互联网未来科技 狮子座互联网科技有限公司 互联网 科技服务平台 济南华为互联网科技产业总部基地 上海宁丞科技互联网 青岛科技大学互联网大赛研究生 江苏互联网智能科技软件 张召忠谈中国互联网科技 宇信科技在杭州互联网排第几 山东大美朱楼互联网科技有限公司 全球科技与互联网公司市值变化 容联科技互联网电商 互联网公司 科技公司 博兴的互联网电子科技公司 互联网科技博主是什么意思 广州恒生互联网科技有限 赶超互联网科技 微信多开 电子科技大学互联网创业大赛 青海科技产业互联网发展 深圳市罗太互联网科技有限公司 有人说阿里系是互联网科技企业 承德科技产业互联网平台
0