In our previous post, “GuidV7 Considerations for Database Keys,” we looked at how GuidV7 generation for multiple values with the same timestamp presents a challenge: the generated values sort differently, affecting the ordering of clustered indexes.

In this post, we look at a different challenge revolving around how SQL Server sorts Guid values.

We will use the same type as before:

public sealed record Thing(Guid ID, string Caption);

We then have the following SQL Server table schema:

create table things
(
    id      uniqueidentifier not null
        constraint things_pk
            primary key,
    caption nvarchar(100)
);

We then generate some Guid values in v7 format, ensuring a unique timestamp.

using Dapper;
using Microsoft.Data.SqlClient;

const string connectionString =
    "data source=localhost;uid=sa;password=YourStrongPassword123;database=things;trustservercertificate=true";
var things = new List<Thing>();
for (var i = 0; i < 10; i++)
{
    things.Add(new Thing(Guid.CreateVersion7(), $"{i}"));
    Thread.Sleep(TimeSpan.FromMilliseconds(1));
}

foreach (var thing in things)
{
    Console.WriteLine($"ID: {thing.ID}; {thing.Caption}");

    using (var cn = new SqlConnection(connectionString))
    {
        cn.Execute("insert into things(id,caption) values (@ID,@Caption)", thing);
    }
}

This will print something like this:

sqlgeneration

If we go to the database and order by ID

sqlgenerationDatabase

We can see here that they are not ordered as we would expect.

We can verify that the Guid values should sort by creation order.

var list = new List<Guid>();
list.Add(Guid.Parse("019fec37-b43f-711b-9eca-235bd6832c05"));
list.Add(Guid.Parse("019fec37-b440-7bd1-9e7f-78b083c146d8"));
list.Add(Guid.Parse("019fec37-b441-7049-af14-ec04cccac53c"));
list.Add(Guid.Parse("019fec37-b443-72e9-8b11-2e0a5b9b44e3"));
list.Add(Guid.Parse("019fec37-b444-79a5-a9b2-985625835097"));
list.Add(Guid.Parse("019fec37-b445-7dd3-a572-b1279071dea0"));
list.Add(Guid.Parse("019fec37-b446-733c-bcf9-f2e3a3d089bd"));
list.Add(Guid.Parse("019fec37-b448-79be-bfa9-1da3d0f27dd6"));
list.Add(Guid.Parse("019fec37-b449-7d69-8946-ce0ba11237bb"));
list.Add(Guid.Parse("019fec37-b44a-7076-8e44-0e48ae84c5be"));
list.Sort();

list.ForEach(x => Console.WriteLine(x));

This should print the same sequence as creation:

orderedGuids

The issue is around how Guid values are sorted by SQL Server - it does not use the algorithm for Guid v7.

This essentially means Guid.CreateVersion7() does not create values that SQL Server will correctly order for a clustered index.

TLDR

SQL Server does not sort Guid values using an algorithm congruent with v7.

The code is in my GitHub.

Happy hacking!