在SQL中发现了很大的性能差异(1小时到1分钟)。你能解释一下原因吗?
-
10-07-2019 - |
题
以下查询分别在100万条记录的标准机器上花费70分钟和1分钟。可能的原因是什么?
查询[01:10:00]
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
, sys.fn_cdc_get_max_lsn()
, 'all with mask')
WHERE __$operation <> 1
修改查询[00:01:10]
DECLARE @MinLSN binary(10)
DECLARE @MaxLSN binary(10)
SELECT @MaxLSN= sys.fn_cdc_get_max_lsn()
SELECT @MinLSN=CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
@MinLSN, @MaxLSN, 'all with mask') WHERE __$operation <> 1
[变形]
我尝试使用类似的函数重新创建场景,以查看是否为每一行评估参数。
CREATE FUNCTION Fn_Test(@a decimal)RETURNS TABLE
AS
RETURN
(
SELECT @a Parameter, Getdate() Dt, PartitionTest.*
FROM PartitionTest
);
SELECT * FROM Fn_Test(RAND(DATEPART(s,GETDATE())))
但是,对于在38秒内处理的一百万条记录,我获得了“参数”列的相同值。
解决方案
甚至确定性标量函数每行至少评估一次。如果相同的确定性标量函数在同一个<!>“行<!>”上多次出现;使用相同的参数,我相信只有这样才会被评估一次 - 例如在CASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 END
或类似的东西。
我认为你的兰德问题是因为你继续研究:
重复调用RAND() 相同的种子值返回相同 结果。
对于一个连接,如果是RAND() 使用指定的种子值调用, 随后的所有RAND()调用都会产生 基于种子兰德()的结果 呼叫。例如,以下查询 将始终返回相同的序列 数字。
我已经指出了缓存标量函数结果 - 甚至可以预先计算标量函数结果表并加入它们。最终必须做一些事情以使标量函数执行。没错,最好的选择是CLR - 显然这些远远超过SQL UDF。不幸的是,我不能在我目前的环境中使用它们。
其他提示
在第一个查询中,您的fn_cdc_increment_lsn
和fn_cdc_get_min_lsn
会为每一行执行。在第二个例子中,只有一次。
不隶属于 StackOverflow