对于大型数据集,使用 an 进行分页OFFSET是众所周知的,并且不是最好的分页方式。更好的分页方式是使用游标,它只是行上的一个唯一标识符,因此我们知道从最后一个光标位置上次离开的位置继续分页的位置。
当涉及到一个自动递增id值的游标时,实现起来相当容易:
SELECT * FROM users
WHERE id <= %cursor // cursor is the auto incrementing id, ex. 100000
ORDER BY id DESC
LIMIT %limit
Run Code Online (Sandbox Code Playgroud)
我们不确定的是,如果不是自动递增id游标,游标的唯一唯一顺序标识符是表行上的uuid和created_at。
我们当然可以根据 查询uuid得到created_at,然后选择所有的users,<= created_at但问题是如果表中有多个相同created_at时间戳的实例users怎么办?知道如何users根据uuid/created_at游标组合查询表以确保我们获得正确的数据集(就像我们使用自动递增一样id)?再次,只有独特的领域是uuid因为created_at可能是重复的,但他们的组合是每行唯一的。
我在我的 Postgres 数据库上使用 uuids 的键集分页方法,如本文所述:
但是,我注意到当我有两条日期相同的记录时,会从结果中跳过行。
例如,当我运行查询时:
SELECT id, created_at FROM collection
ORDER BY created_at DESC, id DESC
Run Code Online (Sandbox Code Playgroud)
我按照我的预期取回了记录,作为created_at主要顺序,然后id充当决胜局:
| ID | 创建时间 |
|---|---|
| e327847a-7058-49cf-bd91-f562412aedd9 | 2022-05-23 23:07:22.592 |
| d35c6bb8-06dd-4b86-b5c6-d123340520e2 | 2022-05-23 23:07:22.592 |
| 5167cf95-953f-4f7b-9881-03ef07adcf3c | 2022-05-23 23:07:22.592 |
| d14f48dc-df22-4e98-871a-a14a91e8e3c1 | 2022-05-23 23:07:21.592 |
但是,当我运行查询来分页时,例如:
SELECT id, created_at
FROM collection
WHERE (created_at, id) < ('2022-05-23 23:07:22.592','d35c6bb8-06dd-4b86-b5c6-d123340520e2')
ORDER BY created_at DESC, id DESC
LIMIT 3
Run Code Online (Sandbox Code Playgroud)
我希望取回最后两条记录,但我的结果集是
| ID | 创建时间 |
|---|---|
| d14f48dc-df22-4e98-871a-a14a91e8e3c1 | 2022-05-23 23:07:21.592 |
我还尝试了查询的一些变体来尝试修复它,例如:
SELECT id, created_at
FROM collection
WHERE created_at < '2022-05-23 23:07:22.592' OR
(created_at …Run Code Online (Sandbox Code Playgroud)