-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve our SQL Server client-generated GUIDs #33579
Comments
@JackTrapper would you be interested in submitting a PR for this? EF's client-side GUID generator for SQL Server is in https://github.com/dotnet/efcore/blob/main/src/EFCore/ValueGeneration/SequentialGuidValueGenerator.cs. |
dotnet/runtime#103658 was completed recently and .NET 9 will contain |
@cremor I'm not sure, this will require some careful investigation. |
I searched a bit more and it looks like UUID v7 (which is used by the new See: |
I'm certain it will not help for SQL Server because it does not tailor itself to SQL Server's sort order. Which is appropriate; it is correct for C# to be agnostic to SQL Server, Oracle, DB2, Postgres. No, this feature needs to be a database client feature. And it's not like one-size-fits all, because different databases use different sort rules. No, what you need is:
I don't believe any other database engines have a So there is no such thing as a one-size-fits-all solution. You have to know you are generating a UUID to be fed to Microsoft SQL Sever. I don't know where/if in EF Core you tell it the flavor of database engine you're using-so that way it can adjust the bits of a standard type-1 uuid to make is collation compatible with the database back-end engine. No matter what you want to start with UuidCreateSequential (or the local OS's equivalent) becuase there are rules about how to handle two UUIDs being generated within the same 100 ns tick. And it's not an issue you can ignore; modern CPUs are fast enough you can generate 200,000 UUIDs in the same 100 ns tick. The solution is the system-wide collision counter documented in the RFC, and already implemented on Windows by UuidCreateSequential. Once you have your type-1 uuid created by UuidCreateSequential, you then have to move the bytes around so that the 64-bit (8-byte) timestamp is sorted first. So, no, any implemenation of Guid.CreateVersion7() will not be useful here, since it was not designed with my specific favorite database engine in mind. |
Uuidnext has a variant of uuid v8 that is sortable in ms sql server : https://github.com/mareek/UUIDNext/blob/main/Src/UUIDNext/Generator/UuidV8SqlServerGenerator.cs |
I ran your code for sortable guids in (https://github.com/dotnet/efcore/issues/30753#issuecomment-2027429203)[his comment] on #30753. I found that it does not significantly differ from the earlier mentioned GUID generation strategies. The GUIDs generated used an average page space of 67%, and fragmentation was 41%. I have upgraded hardware at this point, so there could be some skew in there. I'm wondering if maybe there's something wrong with my testing methodology now, though, as this seems really bad for something that seems so well documented and thought out. Is there any chance that you can explain why I got such a high fragmentation %? |
I'd have to say:
|
There's a report that our current client-side sequential GUIDs generator for SQL Server doesn't work well for concurrent environments; #30753 was opened to consider switching to server-generated GUIDs instead, as a way of mitigating that.
However, @JackTrapper posted an analysis in #30753 (comment), according to which the issue could be mitigated by improving the client-side generation logic instead. If this indeed makes our client-generated GUIDs as indexing-efficient as server-side ones generated via NEWSEQUENTIALID, that would be a good improvement that should also maintain EF backwards compatibility.
The text was updated successfully, but these errors were encountered: