Daily Knowledge Drop
Often Guids
are used as database primary keys, as they are "guaranteed" to be unique and random or un-guessable. However one drawback of them, is that due to their uniqueness there is no ordering, which leads to index fragmentation, an increase in database size, as well as a potential performance degradation.
The NewId library, can assist with this, by generating unique, but sortable Guids
.
Guid
In C#, Guid's
are mostly created using the Guid.NewGuid
method (there are other ways, such as using this technique to create a deterministic Guid)
Using Guid.NewGuid
to created 10 Guids
:
for (int i = 0; i < 10; i++)
{
var id = Guid.NewGuid();
Console.WriteLine(id);
}
We can see, as by design, the values of the 10 Guids
are random and are unrelated to one another:
7620e975-26e6-46ca-876d-dff93495ad57
24751db7-6372-4b8c-94fd-2ae3ad92f926
c8791bf1-f85a-4b12-81e7-18cab1516cb9
5a78214c-adb6-4d59-8921-bca021b50b22
e46a7e0e-faf4-4af3-bd2e-39a1102af894
807ad5c4-7314-4ebb-8914-3b9a0f38386f
ca536113-ea85-41a6-844f-891d8aab40e4
44cf6ff1-89da-458f-8f69-57d4c68c73cf
b18e4911-e439-4506-9f23-b5017ce82d55
225557ab-a5eb-48e1-b04e-7a72696e85ca
As mentioned, having unique values is the desired goal, but having them be completely random can cause issues if they are being used as database primary keys.
The non-sequential nature of this approach leads to index fragmentation, but also means records cannot be sorted by this field, and requires another field (e.g. DateCreated) to be sortable.
NewId
The Newid library addresses these issues, by creating unique, semi-random, sortable Ids
.
The library is very easy to use, with the NewId.Next()
method used to produce an Id
. It is also possible to set a start Id
, or a start byte-array, from quick subsequent Ids
are based.
Using NewId
to created 10 Ids
:
for (int i = 0; i < 10; i++)
{
var newId = NewId.Next().ToGuid();
Console.WriteLine(newId);
}
The 10 unique, but sortable Guids
are as follows:
df1d0000-0a83-7cd3-fdf2-08da40cae578
df1d0000-0a83-7cd3-467a-08da40cae579
df1d0000-0a83-7cd3-48ba-08da40cae579
df1d0000-0a83-7cd3-49de-08da40cae579
df1d0000-0a83-7cd3-4aba-08da40cae579
df1d0000-0a83-7cd3-4b95-08da40cae579
df1d0000-0a83-7cd3-4c93-08da40cae579
df1d0000-0a83-7cd3-4d6e-08da40cae579
df1d0000-0a83-7cd3-4e8b-08da40cae579
df1d0000-0a83-7cd3-4f5c-08da40cae579
As one can see, the Guids
are unique and sorted, but don't look entirely random - this is because some parts are in fact not entirely random.
The Id
generated is made up of three portions:
df1d0000-0a83-7cd3
: this portion is the same for allIds
generated by the same process/worker Id. This will be constant on a particular machine, but will differ PC to PC.4f5c
: this portion will change with eachId
generated.08da40cae579
: this portion increments, but slowly and not for everyId
generated (as is evident in the the above example)
There are three sources of information are used to construct the Id
:
- A
process/worker Id
: unique and constant for each PC - A
timestamp
: by definition, incrementing and thus orderable - A
sequence
: this is an incrementing Id
Generating a NewId
is just as easy as generating a Guid
directly - and are directly convertible to a Guid
(as was done in the above code example)
Notes
NewId
is not suitable for every situation - in some cases you would want the generated Id
to be completely random and un-guessable. However, if you are using Guids
as database primary keys, consider using NewId
to generate the Ids
instead of Guid.NewGuid.
I appreciate the fact that, while the library does generate its own type (also called NewId), this type is effectively a Guid
, and can easy be converted to one. This means that any underlying entities which currently use a Guid
do not need to be updated with a new type, or reference a third party package - they can be kept "clean".
References
NewId
Generating sortable Guids using NewId
Daily Drop 98: 17-06-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.On This Page