Hello everybody
Recently, some of my colleagues talked about database ids
and uuids
and their problems, and I remembered the pain of working with randomly distributed primary keys. They’re nice at first but then you have to index and order by a different field like created_at
, while serial
and bigserial
already have an order and are indexed as the primary key.
UUIDv6, UUIDv7 and UUIDv8 are new standards to deal with issues found in UUIDv4 and earlier. I especially liked this post that analyzes the new standards: https://blog.devgenius.io/analyzing-new-unique-identifier-formats-uuidv6-uuidv7-and-uuidv8-d6cc5cd7391a
My favourite is UUIDv7 because they’re like UUIDv4 but the first characters are based on a millisecond timestamp; it seems like a very small change.
Elixir doesn’t have a common implementation of UUIDv7 yet, and Ecto is based on UUIDv4. So I decided to build one based on a Rust package https://crates.io/crates/uuid, which is relatively mature.
The new library is called UUIDv7 and is available on Hex UUIDv7 - Hex.
Because it’s based on Rust, the UUID generation is a whopping 72% faster than the default Ecto.UUID
version 4 generator. NIFs are precompiled and generated for most platforms.
It’s easy to set up, you only have to change one line:
def App.Schemas.User do
use Ecto.Schema
@primary_key {:id, UUIDv7, autogenerate: true}
end
You can verify the UUIDs are ordered by running a small test:
uuid1 = UUIDv7.generate()
uuid2 = UUIDv7.generate()
uuid3 = UUIDv7.generate()
uuid4 = UUIDv7.generate()
assert uuid1 < uuid2
assert uuid2 < uuid3
assert uuid3 < uuid4
Though you may have to add Process.sleep(1)
between the generations to skip one millisecond (UUIDv7 is based on milliseconds and ends with random bits)
Since the performance difference between Rust-based UUID generation and Ecto.UUID is so large, maybe it could be a motivation to write other more commonly used functions as NIFs from more compute-efficient languages?
You can check the benchmark here: UUIDv7 - Benchmark
GitHub: UUIDv7 - GitHub
Hex: UUIDv7 - Hex