SonnetDB 支持 LIMIT ... OFFSET 和 OFFSET ... FETCH 两种 SQL 分页写法。它们可以表达同一个"跳过若干匹配行,再返回一页"的查询;分页是否稳定,还取决于排序、筛选条件和连续请求期间的数据变化。
用一组时序数据理解分页
下面的示例限定同一个 host,并使用三个不同的时间戳:
sql
CREATE MEASUREMENT cpu (
host TAG,
usage FIELD FLOAT
);
INSERT INTO cpu (time, host, usage) VALUES
(1700000000000, 'server-01', 10),
(1700000001000, 'server-01', 20),
(1700000002000, 'server-01', 30);
LIMIT 与 OFFSET
sql
SELECT time, host, usage
FROM cpu
WHERE host = 'server-01'
ORDER BY time ASC
LIMIT 2 OFFSET 1;
这里先按时间升序排列匹配结果,跳过第一行,再返回最多两行。OFFSET 从零开始;LIMIT 2 省略 OFFSET 时,从第一条匹配结果开始。
OFFSET 与 FETCH
同一页也可以写成:
sql
SELECT time, host, usage
FROM cpu
WHERE host = 'server-01'
ORDER BY time ASC
OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY;
OFFSET 1 ROWS 指定跳过一行,FETCH NEXT 2 ROWS ONLY 指定最多取两行。SonnetDB 接受 ROW 与 ROWS,FETCH 子句的 ONLY 不能省略。
可以省略 OFFSET
当前解析器也支持直接取开头几行:
sql
SELECT time, host, usage
FROM cpu
WHERE host = 'server-01'
ORDER BY time ASC
FETCH FIRST 2 ROWS ONLY;
这时偏移量为零。不要把标准风格误写成"必须同时出现 OFFSET 和 FETCH"。此外,OFFSET 1 单独出现表示跳过一行并返回剩余匹配结果,并不限制页大小。
| 目的 | LIMIT 风格 | FETCH 风格 |
|---|---|---|
| 取开头两行 | LIMIT 2 |
FETCH FIRST 2 ROWS ONLY |
| 跳过一行再取两行 | LIMIT 2 OFFSET 1 |
OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY |
分页数量应为非负整数。当前解析器还允许参数占位符;应用应通过客户端参数绑定传入页大小和偏移量,而不是拼接不可信文本。
排序与连续请求的边界
列表分页应显式指定 ORDER BY。仅写 ORDER BY time,并不能让拥有相同时间戳的多条记录获得跨请求稳定的先后次序;需要结合数据模型选择能消除并列的排序键。示例中的单 host、不同时间戳只是一个便于理解的受控输入。
分页语法也不自动提供跨请求快照。两次请求之间发生插入或删除时,OFFSET 对应的行位置可能变化,应用需自行定义一致性要求。
深分页可以考虑时间边界
当偏移量越来越大,查询仍需处理并跳过相应的匹配行;带排序、过滤或阻塞算子的成本还取决于实际执行路径。不能从小 LIMIT 推导固定的扫描量、内存占用或性能收益。
对示例中时间戳不重复的数据,可以把上一页最后一个时间戳作为下一页的下界:
sql
SELECT time, host, usage
FROM cpu
WHERE host = 'server-01'
AND time > 1700000001000
ORDER BY time ASC
LIMIT 2;
如果数据允许多条记录共享时间戳,仅使用 time > 上一页末尾时间 会漏掉尚未返回的同时间戳记录。应使用能完整表达排序边界的游标方案,并核对对应模型及查询形态的支持范围。时间条件不自动构成服务端续页 token,也不保证生产性能。