VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
The MySQL Default: UUID() as CHAR(36)
MySQL’s built-inUUID() function returns a v1 UUID as a 36-character string like 550e8400-e29b-41d4-a716-446655440000. Storing that in a CHAR(36) column works, but it’s inefficient:
- 36 bytes instead of 16 for the same data
- String comparison is slower than binary comparison
- Random UUIDs cause B-tree page splits on every insert (more on this below)
The Standard Workaround: BINARY(16)
MySQL providesUUID_TO_BIN() and BIN_TO_UUID() to convert between string and compact binary form. Using BINARY(16) cuts storage in half and speeds up comparisons:
UUID_TO_BIN() takes an optional second argument (1) that reorders the timestamp bits so v1 UUIDs sort chronologically — a partial fix for the insert performance problem.
The Remaining Problem: Random Inserts Fragment Indexes
MySQL’s InnoDB uses a clustered index, meaning rows are physically stored in primary key order. When you insert a row with a random UUID, InnoDB has to find where it goes in the middle of the index and potentially split a page to make room. Under sustained load, this causes write amplification and index fragmentation. UUID v7 fixes this by embedding a Unix timestamp in the high bits of the identifier. New UUIDs are always larger than existing ones, so inserts always append to the rightmost leaf of the index — no splits.With VillageSQL: Native UUID Type and All Versions
VillageSQL’svsql_uuid extension adds a native UUID column type with 16-byte binary storage and no manual conversion, plus generation functions for UUID v1 through v7.
Choosing a UUID version
UUID_VERSION(uuid) returns the version number of a stored UUID — useful for routing IDs by version. It accepts a UUID value or a string literal, which is converted implicitly — but an invalid string raises ERROR 1525 instead of returning 0 or NULL, so it is not the tool for screening untrusted text; use UUID_IS_VALID() below for that. UUID_COMPARE(uuid1, uuid2) returns -1, 0, or 1 for explicit ordering logic. For a broader look at when to use UUIDs versus other primary key approaches, see Choosing a Primary Key Strategy.
Name-based UUIDs and the RFC namespaces
UUID_V3() and UUID_V5() derive a UUID from a namespace plus a name, so the same pair always produces the same UUID. UUID_NS_DNS(), UUID_NS_URL(), UUID_NS_OID(), and UUID_NS_X500() return the four namespaces RFC 9562 defines. They return text, which is what the namespace parameter takes, so they compose directly:
UUID_NIL() and UUID_MAX() return the all-zeros and all-ones UUIDs the same RFC reserves, for use as sentinel values.
Validating UUIDs from outside the database
UUID_IS_VALID(string) returns 1 when a string would be accepted by a UUID column and 0 when it would not. It never raises, whatever it is handed, so it can screen values before they reach a typed column:
Using UUID functions in generated columns and constraints
The introspection, validation, and constant functions are deterministic, as are the name-based generatorsUUID_V3() and UUID_V5(). All of them can appear in generated columns and CHECK constraints. The random and time-based generators — UUID_V4(), UUID_V7(), and friends — cannot, because their output changes on every call. That lets you derive or validate stored values from a UUID at the schema level:
UUID vs. Auto-Increment
For most single-database applications,
AUTO_INCREMENT is fine. Reach for UUIDs when you need globally unique IDs across systems, when merging data from multiple sources, or when you don’t want to expose sequential row counts.
Frequently Asked Questions
Can I use UUID_V7 as a DEFAULT?
Not currently. Non-deterministic functions can’t be used in DEFAULT expressions in MySQL. Generate the UUID in your INSERT statement.Can I backfill existing rows with UUIDs?
Yes. Add aUUID column, populate it with UUID_V7() in an UPDATE, then make it the primary key.
Is UUID_V7 a standard?
Yes — defined in RFC 9562, which supersedes RFC 4122.Troubleshooting
See also
- Choosing a Primary Key Strategy in MySQL — comparing UUIDs against AUTO_INCREMENT and other strategies
- Generating Random Data in MySQL — the randomness behind UUID v4
- How InnoDB Stores Data — why random UUID primary keys cause page fragmentation

