While searching for UUIDs I stumbled upon ULIDs https://github.com/ulid/spec
And I want to use them in my SQL Server database as primary key for my users (instead of basic incremental value).
So I wanted to ask:
What datatype is the best suited?
uniqueidentifier?binary16? something else? and why?Are there some other extra steps to fully benefit from
ULIDstructure? especially sorting/searching? in comparison to otherUUIDs.
You are after a 16-byte, universally unique, chronologically sortable unique identifier.
SQL Server already has that:
uniqueidentifier.Many people are under the mistaken impression that a
uniqueidentiferis a random value, and that its use as a clusting key is bad because it causes I/O to be scattered all over the place, torn pages, and poor temporaral locality.That is only true for "random" uuids - known as a "type 4" uuids.
Sequential sortable UUIDs
But there are other types of UUIDs:
Rather than being built from random data, or an MD5 hash, or an SHA1 hash, we can use a hash based on a timestamp , with a resolution of
100 ns(i.e.0.0001 ms).And similarly to how you can default a uniqueidentifier colunm to a "type 4 random uuid":
SQL Server also supports sequential type-1 UUIDs:
And those uuids sort chronologically - as long as they're created on the same machine
NodeID, MAC address, and Multiple Machines
There is the issue that the type-1 UUID contains a 6-byte
nodeID, which is the client's MAC address.00112233-4455-6677-8899-AABBCCDDEEFF
And SQL Server, for whatever reason, decided to sort UUIDs by the
nodeIDfirst.SQL Server sorts guids first by f, then e, then d, c, b, a, 9, ..., 2, 1, 0:
In other words, it sorts by:
Node[0]Node[1]Node[2]Node[3]Node[4]Node[5]UInt16 Sequence(little endian)UInt16 TimestampLow(big endian)UInt16 TimestampMid(big endian)UInt32 TimestampHigh(big endian)Which means:
nodeIDs(i.e. MAC address) then you'll have them sorted first by node, and then by timestampThat may or may not be an issue for you. But if it is, the solution is to shuffle around the bytes of the uniqueidentifier/UUID so that:
nodeIDto where the timestamp wasIn C# we use the following class to generate an "SQL Server sortable UUID". Other databases may sort UUIDs/uniqueidentifiers differently.