2016-12-13 53 views
2

通用问题SQL CLR标量函数缓存结果

移动到SQL Server 2014之后,这在以前产生在SQL Server 2008 R2每个执行不同结果的CLR标量函数的执行,现在生产的每个相同的结果随后的通话。

测试/插图

DECLARE @i int = 0; 
WHILE @i < 10 
BEGIN 
    print dbo.getEligLoadTXID(); 
    --> Simulate delay as this code never gets called more than once every few seconds in our environment 
    WAITFOR DELAY '00:00:00.1'; 
    SET @i += 1; 
END; 

目前我们正处在从SQL Server 2008升级我们的环境R2到SQL Server的过程2014年的一个我们已经遇到的问题是具体到执行一个CLR标量函数。功能相对简单;它会根据滴答的数量生成一个内部ID(我们不要争论这个函数的需要/目的)。

在SQL Server 2008 R2环境中,在循环中执行函数会返回预期结果(每次执行都会产生一个新值)。但是,在我们新的SQL Server 2014环境中进行测试时,相同的代码将为循环中的每个执行返回SAME值。

结果在SQL Server 2008 R2:

20161213502167209995 
20161213502168210095 
20161213502169210195 
20161213502170210295 
20161213502171210395 
20161213502172210495 
595 
20161213502174210695 
20161213502175210795 
20161213502176210895 

在SQL Server结果2014:

20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 
20161213502199924787 

我们正在使用此代码生成每个文件中的特定ID,我们得到一个特定的类型。为每个文件生成一个新值,但处理此操作的SSIS进程通常需要4-5秒才能处理每个文件。所以,这个函数每隔几秒就会被完全不同的连接调用一次,但是我们仍然得到了重复的结果。

返回的值确实会周期性变化,所以它不像我们只整天返回一个值,但是对于一段时间,无论是3秒还是30秒,函数都会返回相同的结果。

我们缺少什么?

CLR函数防守

[SqlFunction(IsDeterministic = true, IsPrecise = true)] 
public static String getTransactionID() 
{ 
    DateTime NOW = DateTime.Now; 

    long ticks = NOW.Ticks - new DateTime(NOW.Year, NOW.Month, NOW.Day, 0, 0, 0, 0).Ticks; 

    return String.Format("{0:0000}{1:00}{2:00}{3}", NOW.Year, NOW.Month, NOW.Day, ticks.ToString()); 
} 

回答

5

这是正常现象,从SQL Server 2012的

的问题是,您所指定,通过SqlFunction属性,这个功能应该如何治疗作为“确定性”:

IsDeterministic = true 

确定性函数返回相同的值对于相同的输入值。考虑到你的函数没有任何输入参数,它的所有执行都基本相同。

这种行为是真正确定性功能的巨大性能增益。但是,由于您的函数应该在每次执行时返回不同的值,因此它并不是确定性的。

要解决这个问题,您应该可以设置IsDeterministic = false,或者干脆取消IsDeterministic = true,,因为IsDeterministic的默认值是false

P.S.我知道你说的不是争论,为什么你有这种特殊的功能,但只是在情况下,提及您(或他人)都没有意识到这一点,当前的刻度值应在DMV进行曝光:

SELECT [cpu_ticks] FROM sys.dm_os_sys_info; 

PPS输入参数和返回值最好使用Sql*类型。意思是,使用SqlString而不是String作为返回类型。这可能需要添加using System.Data.SqlTypes;

+1

谢谢你的回应!你不仅回答了我的问题,而且还提供了大量的后续细节。 –