Good intro article. I'd always heard that serial ints aren't guaranteed to be ordered but never knew why (because they are generated non-transactionally..so if an INSERT transaction rolls back the id that would have been used is effectively consumed/skipped). What I see a lot in practice is a bigint numeric id for internal use (better for joins, FKs) and also a textual token for public use, perhaps with a typed prefi…
I guess mean "consecutive" or "sequential" instead of "ordered"
Choosing a Postgres primary key
151–160 of 163 posts
Re: Choosing a Postgres primary key
#152Re: Choosing a Postgres primary key
#153Earlier quoted context omitted.
If your DB supports unsigned integers, or starting sequences from -2,147,483,648, you can double the address range. But if you are at all worried that you'll get within a couple of orders of magnitude of MAXINT32 in the lifetime of your application then you should immediately jump to 64-bit values. Doubling is often just noise and the cost of refactoring if you approach MAXINT32 much faster than expected is more or a…
PostgreSQL doesn't have unsigned integers.
Re: Choosing a Postgres primary key
#154Earlier quoted context omitted.
"Protecting" records by making IDs hard-to-guess just seems like putting the responsibility in the wrong place. If you're so worried about people getting their hands on the wrong records, I'd be more worried about your lack of trust in the application that queries that database in the first place: remember, even if you do make the IDs hard to guess, your "untrusted application" might at some point decide to simply le…
> "Protecting" records by making IDs hard-to-guess just seems like putting the responsibility in the wrong place. It's a pretty powerful implementation of capability based security.
And then people naively copy operating system design methodology into web APIs... Unrevokable leakable know-it-and-you're-in secrets are a bad idea.
Re: Choosing a Postgres primary key
#155Earlier quoted context omitted.
I really hate this trend away from basic IDs. I feel like it's driven by folks who've never actually worked in the real world. I got account paperwork recently where the company ID account ID and invoice ID were all uuids. 100% this company if I call them will not use this BS to lookup my account and will instead use something easier try to guess like a company phone number. I also had to do some support tickets rece…
integer/year works almost flawlessly as invoice ID. It is unique and readable. If the company has more than one unit that creates invoices than just add unit ID, so it becomes invoice_id/unit_id/year. Still unique and very much readable.
https://en.wikipedia.org/wiki/German_tank_problem#Historical...
Re: Choosing a Postgres primary key
#156Earlier quoted context omitted.
Because B-tree indexes are ordered, rows likely to be adjacent on disk (written in time order) are not at all adjacent in the index and vice-versa. There is no "hot page" in the cache representing recent records; the index node you need for any given uuid is random and makes your internal index pages effectively uncacheable. The result is increased IO and cache thrashing.
> Because B-tree indexes are ordered, rows likely to be adjacent on disk (written in time order) are not at all adjacent in the index and vice-versa. But this still doesnt matter, right? If you want time ordering you'd prolly have some field like `created_at`
If those rows have keys that sort near each other, you're changing a few pages.
If those rows have keys that are all over the keyspace, you're changing roughly 1000*k pages.
Re: Choosing a Postgres primary key
#157One more note: uuid is not easily copy-pastable, due to dash `-` in it. I prefer to use it's raw bytes and encode with base32, which is copy-pastable.
If the goal is copy-pastable, why not base36 or base62?
So far https://philzimmermann.com/docs/human-oriented-base-32-encod... has the best trade-offs I've ever seen.
(Though for encoding numbers, where small numbers deserve a shorter representation, Base58 can be nice too.. z-base-32's alphabet is still more user-friendly. https://github.com/tv42/base58 )
Re: Choosing a Postgres primary key
#158I’ve been using HiLo for so long this isn’t something I think about. I don’t see a point in trying to hide the ID. Either it’s public or it’s private and should be verified before being accessed.
Exposing sequential numbers tells your competition the size of your company's user base, user activity levels, and growth.
https://en.wikipedia.org/wiki/German_tank_problem#Historical...
Re: Choosing a Postgres primary key
#159Earlier quoted context omitted.
Because B-tree indexes are ordered, rows likely to be adjacent on disk (written in time order) are not at all adjacent in the index and vice-versa. There is no "hot page" in the cache representing recent records; the index node you need for any given uuid is random and makes your internal index pages effectively uncacheable. The result is increased IO and cache thrashing.
> Because B-tree indexes are ordered, rows likely to be adjacent on disk (written in time order) are not at all adjacent in the index and vice-versa. But this still doesnt matter, right? If you want time ordering you'd prolly have some field like `created_at`
If your index happens to be in a different order (the position in the index is uncorrelated to the position of the row), you're gonna be thrashing pages. This isn't unique to UUID keys - text keys or anything other than current timestamp or serial id are going to have the same problem.
It's really only an issue once your index size exceeds available shared RAM. If you can fit your table's index completely in memory, you probably won't notice. But once you exceed that threshold, performance starts falling off a cliff.
Re: Choosing a Postgres primary key
#160Earlier quoted context omitted.
Not the poster you’re replying to, but with this approach you generally don’t store the hashed identifier. Just encode/decode at the application boundaries.
How do you decode a hash?
What I meant (and have done in the past) is to encrypt/decrypt the auto-incrementing ID at the application boundaries.
If the OP is really using a one-way hash then yes, you would have to store both IDs.