A little context first, then the specific questions will follow.
I am trying to generate sequential GUIDs for use as primary ids in a SQL Server 2008 R2 table. Previously, these were being generated by a user defined function that performed too many string operations to generates sequential GUIDS and it was a performance bottleneck.
To try and decrease the time of this function, I am attempting to use CLR Integration and do the operations within a C# class. The sequentialization of the GUID is being done by updating the last 12 bytes of a GUID to values generated from the system date time.
In the initial version, the GetUTCDate() SQL Server system function was being used to get the date time and convert it to ticks which was then used to create the sequential 12 bytes of a guid. My approach was to use the .NET Framework DateTime.UtcNow.Ticks
property to be converted to the last 12 bytes, but I noticed that the Ticks
property was not being updated as expected and this indicated the system time function was not being called as often as I expected.
To test this, I created a simple method which returns the Ticks:
[SqlFunction()]
public static long GetTicks()
{
return DateTime.UtcNow.Ticks;
}
This assembly for this method was then created as an ASSEMBLY object in SQL Server; note that CLR integration was enabled and the assembly was created in UNSAFE
mode thus allowing access to OS APIs. I then created a function in SQL Server and for this CLR function:
CREATE FUNCTION GetTicks() RETURNS BIGINT
AS EXTERNAL NAME Sequential.Generator.GetTicks;
GO
I then performed the following two statements with the results shown below
SELECT [dbo].[GetTicks]();
SELECT [dbo].[GetTicks]();
The results were:
What this shows is that sequential calls to the CLR Function returned the same value of TICKS. This implies the underlying OS call was not being performed to return ticks for each invocation of the GetTicks()
function. I then performed a second test by creating a simple table like so:
CREATE TABLE #tmp1(
[NUM] [INT] NULL,
[TICKS] BIGINT
);
I populated the table with 300 rows, then executed the following statement:
UPDATE #tmp1
SET [ticks] = [Play].[dbo].[GetTicks]();
I then measured the difference between [ticks] value of consecutive rows and there was only a single change of values out of all 300 rows (done in Excel):
Again, this indicates the Framework DateTime.UtcNow.Ticks
property was not being called for each invocation of the CLR Integrated function GetTicks()
.
Is there a way to enable CLR Integration such that calls to the underlying OS can performed with each invocation of a function from SQL Server?
Is SQL CLR Integration an unwise approach for SQL Server to retrieve the system time from the OS on a basis more frequent than the
GetUTCDATE()
T-SQL function?
Thanks!
(*) Note, the sequential GUIDS are a requirement, I am simply trying to maximize performance of the way they are generated. Additionally, the NEWSEQUENTIALID() function is not acceptable because of the privacy issues.
Additionally, the NEWSEQUENTIALID() function is not acceptable because of the privacy issues
Your design has exactly the same privacy issues. Sequential IDs are fundamentally predictable. – Compound