C# SQL Server CLR集成未按预期调用系统时间
先了解一下上下文,然后再回答具体问题 我正在尝试生成顺序guid,用作sqlserver2008r2表中的主id。以前,这些都是由用户定义的函数生成的,该函数执行了太多的字符串操作,无法生成顺序guid,这是一个性能瓶颈 为了尝试减少此函数的时间,我尝试使用CLR集成并在C#类中执行操作。GUID的顺序化是通过将最后一个GUID更新为从系统日期时间生成的值来完成的 在初始版本中,SQL Server系统函数用于获取日期时间并将其转换为刻度,然后用于创建guid的连续12个字节。我的方法是使用.NET FrameworkC# SQL Server CLR集成未按预期调用系统时间,c#,.net,sql-server,sqlclr,C#,.net,Sql Server,Sqlclr,先了解一下上下文,然后再回答具体问题 我正在尝试生成顺序guid,用作sqlserver2008r2表中的主id。以前,这些都是由用户定义的函数生成的,该函数执行了太多的字符串操作,无法生成顺序guid,这是一个性能瓶颈 为了尝试减少此函数的时间,我尝试使用CLR集成并在C#类中执行操作。GUID的顺序化是通过将最后一个GUID更新为从系统日期时间生成的值来完成的 在初始版本中,SQL Server系统函数用于获取日期时间并将其转换为刻度,然后用于创建guid的连续12个字节。我的方法是使用.N
DateTime.UtcNow.Ticks
属性将其转换为最后12个字节,但我注意到Ticks
属性没有按预期更新,这表明系统时间函数没有按预期的频率被调用
为了测试这一点,我创建了一个简单的方法来返回刻度:
[SqlFunction()]
公共静态长GetTicks()
{
return DateTime.UtcNow.Ticks;
}
然后将此方法的程序集创建为SQL Server中的对象;请注意,已启用CLR集成,并且程序集是在不安全模式下创建的,因此允许访问。然后,我在SQL Server中创建了一个函数,并为此CLR函数:
CREATE函数GetTicks()返回BIGINT
作为外部名称Sequential.Generator.GetTicks;
去
然后,我执行了以下两个语句,结果如下所示
选择[dbo].[GetTicks]();
选择[dbo].[GetTicks]();
结果是:
这表明对CLR函数的顺序调用返回了相同的TICKS值。这意味着没有执行底层操作系统调用来为每次调用GetTicks()
函数返回刻度。然后,我通过创建一个简单的表来执行第二个测试,如下所示:
CREATE TABLE#tmp1(
[NUM][INT]NULL,
[TICKS]BIGINT
);
我用300行填充表,然后执行以下语句:
更新#tmp1
设置[ticks]=[Play].[dbo].[GetTicks]();
然后,我测量了连续行的[ticks]值之间的差异,所有300行中只有一个值发生了变化(在Excel中完成):
同样,这表明没有为CLR集成函数GetTicks()
的每次调用调用调用FrameworkDateTime.UtcNow.Ticks
属性
是否有一种方法可以启用CLR集成,以便每次从SQL Server调用函数时都可以执行对底层操作系统的调用
SQL CLR集成对于SQL Server来说是一种不明智的方法,它从操作系统检索系统时间的频率比GetUTCDATE()
T-SQL函数更高吗
谢谢
(*)注意,顺序guid是一项要求,我只是试图最大限度地提高它们生成方式的性能。此外,由于隐私问题,该功能不可接受
同样,这表明没有为CLR集成函数GetTicks()的每次调用调用调用Framework DateTime.UtcNow.Ticks属性
否,它并不表示未调用UtcNow
属性。问题是.NET中的System.DateTime
的解决方案。无论该值有多精确,该值仅每10-16毫秒递增一次(类似于T-SQL中的GETDATE()
仅每3毫秒更新一次)。这就是为什么该值在一定数量的行中保持不变,但不是像T-SQL datetime函数那样在所有行中都保持不变(例如,GETDATE()
,等等)
是否有一种方法可以启用CLR集成,以便每次从SQL Server调用函数时都可以执行对底层操作系统的调用
“CLR集成”功能为“启用”或“禁用”。除此之外,没有其他配置。如上所述,这是更新DateTime.UtcNow.Ticks
值的频率问题
SQL CLR集成对于SQL Server来说是一种不明智的方法,它从操作系统检索系统时间的频率比GetUTCDATE()T-SQL函数要高吗
与使用GUID/UNIQUEIDENTIFIER
作为PK(我假设它是聚集索引)相比,它本身并不像试图通过引入非内置函数来缓解该决策所导致的性能问题那样不明智
如何调用当前UDF来生成值<代码>插入
触发器
如果性能有问题,则将PK设置为INT
或BIGINT
并使用IDENTITY
。保留GUID字段,但通过向其添加非聚集索引使其成为“备用键”。应用程序代码可以使用GUID值,但是连接等应该使用INT
/BIGINT
PK
但是,从Windows 8/Windows Server 2012开始,就为DateTime.UtcNow.Ticks
获取一个更频繁变化的值而言,有一个新的操作系统功能可以实现这一点。通常我会添加“不幸的是,它要求将程序集标记为不安全的”,因为除非绝对必要,否则应该避免这样做,但您已经提到将程序集标记为不安全的,因此这并没有改变
要使用此新函数,只需从此处获取代码:
然后替换:
DateTime.UtcNow.Ticks
与:
HighResolutionDateTime.UtcNow.Ticks
!!请注意:SQL Se