Skip to content

Commit 2c3863b

Browse files
authored
Merge pull request #23873 from abpframework/article-sequential-guids
Add article on generating sequential GUIDs in .NET
2 parents 019ac06 + 5ad1677 commit 2c3863b

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# You May Have Trouble with GUIDs: Generating Sequential GUIDs in .NET
2+
3+
4+
If you’ve ever shoved a bunch of `Guid.NewGuid()` values into a SQL Server table with a clustered index on the PK, you’ve probably felt the pain: **Index fragmentation so bad you could use it as modern art.** Inserts slow down, page splits go wild, and your DBA starts sending you passive-aggressive Slack messages.
5+
6+
And yet… we keep doing it. Why? Because GUIDs are _easy_. They’re globally unique, they don’t need a round trip to the DB, and they make distributed systems happy. But here’s the catch: **random GUIDs are absolute chaos for ordered indexes**.
7+
8+
## The Problem with Vanilla GUIDs
9+
10+
* **Randomness kills order** — clustered indexes thrive on sequential inserts; random GUIDs force constant reordering.
11+
12+
* **Performance hit** — every insert can trigger page splits and index reshuffling.
13+
14+
* **Storage bloat** — fragmentation means wasted space and slower reads.
15+
16+
Sure, you could switch to int or long identity columns, but then you lose the distributed generation magic and security benefits (predictable IDs are guessable).
17+
18+
## Sequential GUIDs to the Rescue
19+
20+
Sequential GUIDs keep the uniqueness but add a predictable ordering component, usually by embedding a timestamp in part of the GUID. This means:
21+
22+
* Inserts happen at the “end” of the index, not all over the place.
23+
24+
* Fragmentation drops dramatically.
25+
26+
* You still get globally unique IDs without DB trips.
27+
28+
Think of it as **GUIDs with manners**.
29+
30+
## ABP Framework’s Secret Sauce
31+
32+
33+
Here’s where ABP Framework flexes: it **uses sequential GUIDs by default** for entity IDs. No ceremony, no “remember to call this helper method”, it’s baked in.
34+
35+
Under the hood:
36+
37+
* ABP ships with IGuidGenerator (default: SequentialGuidGenerator).
38+
39+
* It picks the right sequential strategy for your DB provider:
40+
41+
* **SequentialAtEnd** → SQL Server
42+
43+
* **SequentialAsString** → MySQL/PostgreSQL
44+
45+
* **SequentialAsBinary** → Oracle
46+
47+
* EF Core integration packages auto-configure this, so you rarely need to touch it.
48+
49+
Example in ABP:
50+
51+
```csharp
52+
public class MyProductService : ITransientDependency
53+
{
54+
private readonly IRepository<Product, Guid> _productRepository;
55+
private readonly IGuidGenerator _guidGenerator;
56+
57+
58+
public MyProductService(
59+
IRepository<Product, Guid> productRepository,
60+
IGuidGenerator guidGenerator)
61+
{
62+
_productRepository = productRepository;
63+
_guidGenerator = guidGenerator;
64+
}
65+
66+
67+
public async Task CreateAsync(string productName)
68+
{
69+
var product = new Product(_guidGenerator.Create(), productName);
70+
await _productRepository.InsertAsync(product);
71+
}
72+
}
73+
```
74+
75+
No `Guid.NewGuid()` here, `_guidGenerator.Create()` gives you a sequential GUID every time.
76+
77+
## Benefits of Sequential GUIDs
78+
79+
Let’s say you’re inserting 1M rows into a table with a clustered primary key:
80+
81+
* **Random GUIDs** → fragmentation ~99%, insert throughput tanks.
82+
83+
* **Sequential GUIDs** → fragmentation stays low, inserts fly.
84+
85+
In high-volume systems, this difference is **not** academic, it’s the difference between smooth scaling and spending weekends rebuilding indexes.
86+
87+
## When to Use Sequential GUIDs
88+
89+
* **Distributed systems** that still want DB-friendly inserts.
90+
91+
* **High-write workloads** with clustered indexes on GUID PKs.
92+
93+
* **Multi-tenant apps** where IDs need to be unique across tenants.
94+
95+
## When Random GUIDs Still Make Sense
96+
97+
* Security through obscurity, if you don’t want IDs to hint at creation order.
98+
99+
* Non-indexed identifiers, fragmentation isn’t a concern.
100+
101+
## The Final Take
102+
103+
ABP’s default sequential GUID generation is one of those “**small but huge**” features. It’s the kind of thing you don’t notice until you benchmark, and then you wonder why you ever lived without it.
104+
105+
## Links
106+
You may want to check the following references to learn more about sequential GUIDs:
107+
108+
- [ABP Framework Documentation: Sequential GUIDs](https://docs.abp.io/en/abp/latest/Guid-Generation)
205 KB
Loading

0 commit comments

Comments
 (0)