什么更快:SUM over NULL 还是 over 0?
What is faster: SUM over NULL or over 0?
我有这样的查询:
select sum(case when col1=@arg1 then value else null end) from t
在性能方面,使用 0
而不是 NULL
有区别吗?像这样:
select sum(case when col1=@arg1 then value else 0 end) from t
DECLARE @type CHAR(2) = 'U'
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 END)
FROM sys.objects
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 ELSE NULL END)
FROM sys.objects
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 ELSE 0 END)
FROM sys.objects
结果:
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 6 ms.
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.
所以...答案 - 相似(如果我们只谈论性能)
在下面的测试中,我始终发现 NULL
稍微快一些。
SET STATISTICS TIME ON;
DECLARE @i int = null; /*Or set to zero*/
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
SELECT SUM(@i) FROM E8
OPTION (MAXDOP 1)
聚合 100,000,000 个值平均需要 608 毫秒。 (即每次聚合 6 纳秒)。
NULL
人在
上花费的时间更多
sqllang.dll!CESRunTimeErrorSink::SetAggFnSkippedNull
大概设置了导致消息的标志
Warning: Null value is eliminated by an aggregate or other SET
operation.
但总体上似乎更快(下面以毫秒为单位的经过时间)。
+---------+--------+------++-------+
| | NULL | 0 || Diff |
+---------+--------+------++-------+
| Trial 1 | 7027 | 7592 || 565 |
| Trial 2 | 6981 | 7743 || 762 |
| Trial 3 | 7451 | 8015 || 564 |
| Trial 4 | 6997 | 7591 || 594 |
| Trial 5 | 7018 | 7574 || 556 |
+---------+--------+------++-------+
| Avg | 7094.8 | 7703 || 608.2 |
+---------+--------+------++-------+
当然,在这种情况下(所有输入都是 NULL
),它们 return 不同的结果,如果您想互换处理这两者,则需要 ISNULL(SUM(@i),0)
。
我有这样的查询:
select sum(case when col1=@arg1 then value else null end) from t
在性能方面,使用 0
而不是 NULL
有区别吗?像这样:
select sum(case when col1=@arg1 then value else 0 end) from t
DECLARE @type CHAR(2) = 'U'
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 END)
FROM sys.objects
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 ELSE NULL END)
FROM sys.objects
-- [Expr1042] = Scalar Operator(CASE WHEN [Expr1048]=(0) THEN NULL ELSE [Expr1049] END)
SELECT SUM(CASE WHEN [type] = @type THEN 1 ELSE 0 END)
FROM sys.objects
结果:
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 6 ms.
Table 'sysschobjs'. Scan count 1, logical reads 1556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.
所以...答案 - 相似(如果我们只谈论性能)
在下面的测试中,我始终发现 NULL
稍微快一些。
SET STATISTICS TIME ON;
DECLARE @i int = null; /*Or set to zero*/
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
SELECT SUM(@i) FROM E8
OPTION (MAXDOP 1)
聚合 100,000,000 个值平均需要 608 毫秒。 (即每次聚合 6 纳秒)。
NULL
人在
sqllang.dll!CESRunTimeErrorSink::SetAggFnSkippedNull
大概设置了导致消息的标志
Warning: Null value is eliminated by an aggregate or other SET operation.
但总体上似乎更快(下面以毫秒为单位的经过时间)。
+---------+--------+------++-------+
| | NULL | 0 || Diff |
+---------+--------+------++-------+
| Trial 1 | 7027 | 7592 || 565 |
| Trial 2 | 6981 | 7743 || 762 |
| Trial 3 | 7451 | 8015 || 564 |
| Trial 4 | 6997 | 7591 || 594 |
| Trial 5 | 7018 | 7574 || 556 |
+---------+--------+------++-------+
| Avg | 7094.8 | 7703 || 608.2 |
+---------+--------+------++-------+
当然,在这种情况下(所有输入都是 NULL
),它们 return 不同的结果,如果您想互换处理这两者,则需要 ISNULL(SUM(@i),0)
。