I have a table called event which has id (uuidv4), name, description, created_at and updated_at columns.
I am trying to understand "keyset pagination". This is what I understand right now:
Base query (first page):
SELECT *
FROM event
ORDER BY created_at, id ASC
LIMIT 3
Second query (second page):
SELECT *
FROM event
WHERE (created_at, id)
> ('2024-02-09 14:21:52+00', '7aa20cad-3a8f-45cb-bee2-2115d4ad1c20')
ORDER BY created_at, id ASC
LIMIT 3;
This works perfectly. But I have a few use-cases which I don't understand.
What happens when I want to order by
created_at DESCorid DESC?How does it work if I want to order by
name DESC?SELECT * from event ORDER BY name DESC, created_at, id ASC LIMIT 3. But how does that work when fetching with a cursor? I know that I have to include the name in the cursor but I don't understand how the tuple filter then would look like:SELECT * FROM event WHERE (name, created_at, id) > ('Name 9', '2024-02-09 14:21:52+00', '7aa20cad-3a8f-45cb-bee2-2115d4ad1c20') ORDER BY created_at, id ASC LIMIT 3;Like this? But does the
<or>operator not correlate to the ordering?
Can someone point to resources explaining it well, or explain it here?
"Keyset pagination" with index support (the only kind that performs well) is based on Row Constructor Comparison. The comparison uses the same operator for every field in the row ("key in the set"). And the index has to agree with that: use the same fields in the same sequence and all with either ascending or descending sort order. You cannot mix ascending and descending order in either the query or the index. See:
Consequently, beware of columns that aren't defined
NOT NULLin the row value (the "keyset") used for sorting.NULLsorts last in defaultASCENDINGsort order (and first indDESCENDINGorder), but a row value comparison like:... excludes rows with null values in the
namecompletely. The manual: