可用版本:Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

SEEK子句

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

前面的章节讨论了使用 LIMIT .. OFFSETOFFSET .. FETCH 或其他一些供应商特定的变体来进行 OFFSET 分页。 当达到较高的页码时,这可能会导致严重的性能问题,因为数据库需要跳过所有不需要的记录。

一种更快,更稳定的分页方法是所谓的键集分页方法,也称为查找方法。 jOOQ 支持一个合成的 seek() 子句,可用于执行键集分页(了解 其他合成 SQL 语法)。 假设我们有这些数据

+------+-------+---------------+
|   ID | VALUE | PAGE_BOUNDARY |
+------+-------+---------------+
|  ... |   ... |           ... |
|  474 |     2 |             0 |
|  533 |     2 |             1 | <-- Before page 6
|  640 |     2 |             0 |
|  776 |     2 |             0 |
|  815 |     2 |             0 |
|  947 |     2 |             0 |
|   37 |     3 |             1 | <-- Last on page 6
|  287 |     3 |             0 |
|  450 |     3 |             0 |
|  ... |   ... |           ... |
+------+-------+---------------+

现在,如果我们想向用户显示第 6 页,我们可以只获取严格位于第 5 页最后一条记录之后的记录,而不是使用记录 OFFSET 转到第 6 页,这样会得到值 (533, 2)。 以下是如何使用 SQL 或 jOOQ 来实现

SELECT id, value
FROM t
WHERE (value, id) > (2, 533)
ORDER BY value, id
LIMIT 5
 
DSL.using(configuration)
   .select(T.ID, T.VALUE)
   .from(T)
   .orderBy(T.VALUE, T.ID)
   .seek(lastValue, lastId) // from last page: value = 2, id = 533
   .limit(5)
   .fetch();

如您所见,jOOQ SEEK 子句是一个合成子句,它在 SQL 中并不真正存在。 但是,由于多种原因,jOOQ 语法更直观

  • 它替换了您期望的 OFFSET
  • 它不会强迫您将常规谓词与“查找”谓词混合使用
  • 它是类型安全的
  • 它为您模拟行值表达式谓词,在那些不支持它们的数据库中

此查询现在产生

+-----+-------+
|  ID | VALUE |
+-----+-------+
| 640 |     2 |
| 776 |     2 |
| 815 |     2 |
| 947 |     2 |
|  37 |     3 |
+-----+-------+

请注意,您不能将 SEEK 子句与 OFFSET 子句结合使用。

有关此强大功能的更多信息,请参见 jOOQ 博客

有关 offset 分页与键集分页性能的更多信息,请访问我们的合作伙伴页面

反馈

您对此页面有任何反馈吗? 我们很乐意听取您的意见!

The jOOQ Logo