News for hackers. Stuff that matters.
Re:PostgreSQL and UUID as Primary Key by badestrand on Saturday July 06, 2024 @03:08AM (#40888678)
You never expose the bigserial, you generate a ID (like UUID) for external use/identification and simply have an index over that column for fast selects.
Re:PostgreSQL and UUID as Primary Key by stoperaticless on Saturday July 06, 2024 @05:30AM (#40889251)
Amen (or similar)
Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @06:05AM (#40889375)
Having an index over the uuid is equivalent to it being a PK, so why would you bother having both?
Re:PostgreSQL and UUID as Primary Key by blackenedgem on Saturday July 06, 2024 @06:15AM (#40889429)
Because it's much better for range queries and joins. When you inevitably need to take a snapshot of the table or migrate the schema somehow you'll be wishing you had something else other than a UUID as the PK.
Re:PostgreSQL and UUID as Primary Key by rezonant on Saturday July 06, 2024 @07:47AM (#40889831)
This. Highly recommend using a numeric primary key + UUID. Using UUID relations internally can have some strategic advantages, but when UUIDv4 is used as the only primary key, you completely lose the ability to reliably iterate all records across multiple independent queries.

Also, the external thing isn't just for exposing it out to your own apps via APIs, but way more importantly for providing an unmistakable ID to store within external related systems. For example, in your Stripe metadata.

Doing this ensures that ID either exists in your own database or does not, regardless of database rollbacks, database inconsistencies etc. In those situations a numeric ID is a big question mark: Does this record correspond with the external system or was there a reuse of that ID?

I've been burnt taking over poorly managed systems that saved numeric IDs externally, and in trying to heal and migrate that data, ran into tons of problems because of ill-considered rollbacks of the database. At least after I leave the systems I build won't be subtly broken by such bad practices in the future.

Re:PostgreSQL and UUID as Primary Key by groestl on Saturday July 06, 2024 @07:11AM (#40889678)
Ha? Please elaborate.
Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @07:28AM (#40889751)
When running a batched migration it is important to batch using a strictly monotonic field so that new rows wont get inserted in already processed range
Re:PostgreSQL and UUID as Primary Key by asah on Saturday July 06, 2024 @08:46AM (#40890114)
would creation/lastmod timestamps cover this requirement?
Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @11:09AM (#40890861)
Yes, although timestamps may have collisions depending on resolution and traffic, no? Bigserials (at least in PG), are strictly monotonic (with holes).
Re:PostgreSQL and UUID as Primary Key by blackenedgem on Saturday July 06, 2024 @09:44AM (#40890428)
It's not even necessarily it being strictly monotonic. That part does help though as you don't need to skip rows.

For me the bigger thing is the randomness. A uid being random for a given row means the opposite is true; any given index entry points to a completely random heap entry.

When backfilling this leads to massive write amplification. Consider a table with rows taking up 40 bytes, so roughly 200 entries per page. If I backfill 1k rows sorted by the id then under normal circumstances I'd expect to update 6-7 pages which is ~50kiB of heap writes.

Whereas if I do that sort of backfill with a uid then I'd expect to encounter each page on a separate row. That means 1k rows backfilled is going to be around 8MB of writes to the heap.

Re:PostgreSQL and UUID as Primary Key by valenterry on Saturday July 06, 2024 @09:55AM (#40890493)
Isn't that solved because UUIDv7 can be ordered by time?
Re:PostgreSQL and UUID as Primary Key by blackenedgem on Saturday July 06, 2024 @10:42AM (#40890732)
Yeah pretty much, although ids can still be a little better. The big problem for us is that we need the security of UUIDs not leaking information and so v7 isn't appropriate.

We do use a custom uuid generator that uses the timestamp as a prefix that rotates on a medium term scale. That ensures we get some degree of clustering for records based on insertion time, but you can't go backwards to figure out the actual time. It's still a problem when backfilling and is more about helping with live reads.

Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @11:10AM (#40890868)
Are page misses still a thing in the age of SSDs?
Re:PostgreSQL and UUID as Primary Key by groestl on Saturday July 06, 2024 @09:48AM (#40890450)
Okay, but in a live DB, typically you won't have only inserts while migrating, won't you?
Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @11:06AM (#40890843)
Yes, but updates are covered by updated app code
Re:PostgreSQL and UUID as Primary Key by x3al on Saturday July 06, 2024 @10:20AM (#40890625)
Strictly monotonic fields are quite expensive and the bigserial PK alone won't give you that.
Re:PostgreSQL and UUID as Primary Key by kroolik on Saturday July 06, 2024 @11:06AM (#40890841)
PG bigserial is already strictly monotonic
Re:PostgreSQL and UUID as Primary Key by blackenedgem on Saturday July 06, 2024 @01:05PM (#40891683)
No they're not, even with a `cache` value of 1. Sequence values are issued at insert rather than commit. A transaction that commits later (which makes all updates visible) can have an earlier value than a previous transaction.

This is problematic if you try to depend on the ordering. Nothing is stopping some batch process that started an hour ago from committing a value 100k lower than where you thought the sequence was at. That's an extreme example but the consideration is the same when dealing with millisecond timeframes.

Re:PostgreSQL and UUID as Primary Key by iterateoften on Saturday July 06, 2024 @06:07AM (#40889388)
If you have an index on the uuid anyways having a separate big serial field for PK doesn’t help that much.
Re:PostgreSQL and UUID as Primary Key by rezonant on Saturday July 06, 2024 @07:55AM (#40889864)
As mentioned elsewhere, it ensures the ability to perform resumable and consistent batching queries across the data set without missing records.

Ordering over an insertion timestamp is not enough if two records may have the same timestamp: You may miss a record (or visit a record twice) across multiple queries.

Re:PostgreSQL and UUID as Primary Key by disneycember on Saturday July 06, 2024 @09:21AM (#40890307)
This is solved sorting by timestamp first then by random PK UUID. Don't think a little simpler batch queries justify leaking time and quantity information or complexity of handling two types of IDs.
Re:PostgreSQL and UUID as Primary Key by j45 on Saturday July 06, 2024 @02:46PM (#40892307)
I agree with not baking more intelligence into a piece of data than needed, especially an index.
Re:PostgreSQL and UUID as Primary Key by rezonant on Saturday July 06, 2024 @04:50PM (#40893171)
You wouldn't expose the numeric IDs publically, and ideally you'd use your database's automatic ID selection to avoid any complexity.

The UUID sorting works in the common case, but if you happen to end your batch near the current time, you still run the risk of losing a few records if the insert frequency is sufficiently high. Admittedly this is only a problem when you are batching through all the way to current insertions.