简体   繁体   中英

Postgres pagination with non-unique keys?

Suppose I have a table of events with (indexed) columns id : uuid and created : timestamp .

The id column is unique, but the created column is not. I would like to walk the table in chronological order using the created column.

Something like this:

SELECT * FROM events WHERE created >= $<after> ORDER BY created ASC LIMIT 10

Here $<after> is a template parameter that is taken from the previous query.

Now, I can see two issues with this:

  1. Since created is not unique, the order will not be fully defined. Perhaps the sort should be id, created ?
  2. Each row should only be on one page, but with this query the last row is always included on the next page.

How should I go about this in Postgres?

SELECT * FROM events 
  WHERE created >= $<after> and (id >= $<id> OR created > $<after>)
  ORDER BY created ASC ,id ASC LIMIT 10

that way the events each timestamp values will be ordered by id. and you can split pages anywhere.

you can say the same thing this way:

SELECT * FROM events 
  WHERE (created,id) >= ($<after>,$<id>)
  ORDER BY created ASC ,id ASC LIMIT 10

and for me this produces a slightly better plan.

an index on (created,id) it will help performance most, but for many circumstances an index on created may suffice.

First, as you said, you should enforce a total ordering. Since the main thing you care about is created , you should start with that. id could be the secondary ordering, a tie breaker invisible to the user that just ensures the ordering is consistent. Secondly, instead of messing around with conditions on created , you could just use an offset clause to return later results:

SELECT * FROM events ORDER BY created ASC, id ASC LIMIT 10 OFFSET <10 * page number>
-- Note that page number is zero based 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM