Fortunately, there's no rule that says you should shard your keys using the sequential part up front.
One of the rules for generating randomness from environmental sources is to throw away the high bits and only use the low bits. Distributed databases should do the same if they want a good distribution.
The closest I’ve ever heard of is sharding based on a hash (e.g. CockroachDB can do this on request[1]) but most distributed databases with strong consistency (Spanner descendants in particular) default to “doing it wrong”.
[1]: https://www.cockroachlabs.com/docs/stable/hash-sharded-index...
We even sharded on these columns, because of this (our business case made it so that hardly ever did people need data over multiple months)
But we never encountered distribution issues. I don't think the locality issue will be solved, as postgres doesn't consider other columns when distributing data, only the primary key IIRC. I don't know why we never saw this, though.
(for folks who don't get it, mullets are a 1980s haircut (think MacGyver) with a short front but a long tail in the back. A funny description of them is "business in the front, party in the back")
If you're using a system which is built for distribution, random is great.
When you're leaning on a Postgres database which has powered your startup through scaling but expects right-leaning btree indexes, it's a bad time.
Rearchitecting to use a new data store is ideal, but often impractical as an immediate step. UUIDv7 is a great increment walking that road via sharding etc.
Somebody posted an interesting article for the instagram ids, which do something similar. They use 41 bits for a time from a custom epoch followed two more groups of bits for a shard id and a sequential number. Each shard has an incrementing sequence for the sequential bit, which guarantees that things on a shard are sorted by time.
This UUIDv7 is slightly weaker than that but sorting things published in the same millisecond is mostly going to be very light work. The lack of a dedicated sharding group of bits is not that important as you could just take the n least significant bits at the end for that without too much effort. Those are random so you end up with nice consistent hashing. Having 48 instead of 41 bits for the time means we won't run out of time any time soon (nearly 9K years vs. 70 years).
Picking the N least significant bits only a single table has good distribution and sort qualities, no cross-table properties.
This is especially useful when your underlying database stores data in large "chunks", such as LSM-trees you find with e.g. rocksdb.
As a sibling comment says, you ideally want to shard on some other key to get "just enough" distribution that all your machines/disks have work to do, but you are still only hitting a limited number of hot sectors on each disk that can be effectively cached. But that requires active monitoring and rebalancing of your data as it grows. Totally random keys are a safe default that will scale with any kind of data distribution and access patterns.
In both cases I'm melding highly disjointed data into a single schema. There are no large consecutive sets of records.
If you're using UUIDs, there's probably a reason. And that reason invalidates the justifications for not using them.
Not really; think of how many architectural decisions are made purely based on imaginary scaling problems, or what the latest blog said.
I would wager that if you polled 100 backend devs, very few of them could correctly articulate the pros and cons of a randomized primary key.
(Or just reverse the bits, take the last n, etc)
I still think that graph databases are way better for this sort of thing.