Đây là thử nghiệm của tôi trên SQL Server 2012 RTM.
if object_id('tempdb..#temp1') is not null drop table #temp1;
if object_id('tempdb..#timer') is not null drop table #timer;
if object_id('tempdb..#bigtimer') is not null drop table #bigtimer;
GO
select a.*
into #temp1
from master..spt_values a
join master..spt_values b on b.type='p' and b.number < 1000;
alter table #temp1 add id int identity(10,20) primary key clustered;
create table #timer (
id int identity primary key,
which bit not null,
started datetime2 not null,
completed datetime2 not null,
);
create table #bigtimer (
id int identity primary key,
which bit not null,
started datetime2 not null,
completed datetime2 not null,
);
GO
--set ansi_warnings on;
set nocount on;
dbcc dropcleanbuffers with NO_INFOMSGS;
dbcc freeproccache with NO_INFOMSGS;
declare @bigstart datetime2;
declare @start datetime2, @dump bigint, @counter int;
set @bigstart = sysdatetime();
set @counter = 1;
while @counter <= 100
begin
set @start = sysdatetime();
select @dump = count(case when number < 100 then 1 end) from #temp1;
insert #timer values (0, @start, sysdatetime());
set @counter += 1;
end;
insert #bigtimer values (0, @bigstart, sysdatetime());
set nocount off;
GO
set nocount on;
dbcc dropcleanbuffers with NO_INFOMSGS;
dbcc freeproccache with NO_INFOMSGS;
declare @bigstart datetime2;
declare @start datetime2, @dump bigint, @counter int;
set @bigstart = sysdatetime();
set @counter = 1;
while @counter <= 100
begin
set @start = sysdatetime();
select @dump = SUM(case when number < 100 then 1 else 0 end) from #temp1;
insert #timer values (1, @start, sysdatetime());
set @counter += 1;
end;
insert #bigtimer values (1, @bigstart, sysdatetime());
set nocount off;
GO
Nhìn vào các lần chạy riêng lẻ và các đợt riêng biệt
select which, min(datediff(mcs, started, completed)), max(datediff(mcs, started, completed)),
avg(datediff(mcs, started, completed))
from #timer group by which
select which, min(datediff(mcs, started, completed)), max(datediff(mcs, started, completed)),
avg(datediff(mcs, started, completed))
from #bigtimer group by which
Kết quả sau khi chạy 5 lần (và lặp lại) là không thuyết phục.
which ** Individual
----- ----------- ----------- -----------
0 93600 187201 103927
1 93600 187201 103864
which ** Batch
----- ----------- ----------- -----------
0 10108817 10545619 10398978
1 10327219 10498818 10386498
Nó cho thấy rằng có nhiều sự thay đổi trong các điều kiện chạy hơn là có sự khác biệt giữa việc thực hiện, khi được đo bằng độ chi tiết của bộ định thời SQL Server. Cả hai phiên bản đều có thể đứng đầu, và phương sai tối đa tôi từng có là 2,5%.
Tuy nhiên, thực hiện một cách tiếp cận khác:
set showplan_text on;
GO
select SUM(case when number < 100 then 1 else 0 end) from #temp1;
select count(case when number < 100 then 1 end) from #temp1;
StmtText (SUM)
|--Compute Scalar(DEFINE:([Expr1003]=CASE WHEN [Expr1011]=(0) THEN NULL ELSE [Expr1012] END))
|--Stream Aggregate(DEFINE:([Expr1011]=Count(*), [Expr1012]=SUM([Expr1004])))
|--Compute Scalar(DEFINE:([Expr1004]=CASE WHEN [tempdb].[dbo].[#temp1].[number]<(100) THEN (1) ELSE (0) END))
|--Clustered Index Scan(OBJECT:([tempdb].[dbo].[#temp1]))
StmtText (COUNT)
|--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1008],0)))
|--Stream Aggregate(DEFINE:([Expr1008]=COUNT([Expr1004])))
|--Compute Scalar(DEFINE:([Expr1004]=CASE WHEN [tempdb].[dbo].[#temp1].[number]<(100) THEN (1) ELSE NULL END))
|--Clustered Index Scan(OBJECT:([tempdb].[dbo].[#temp1]))
Từ đọc của tôi, có vẻ như phiên bản SUM làm được nhiều hơn một chút. Nó đang thực hiện một COUNT ngoài SUM. Đã nói rằng, COUNT(*)
là khác nhau và nên nhanh hơn COUNT([Expr1004])
(bỏ qua NULL, logic hơn). Trình tối ưu hóa hợp lý sẽ nhận ra rằng [Expr1004]
trong SUM([Expr1004])
phiên bản SUM là loại "int" và do đó sử dụng một thanh ghi số nguyên.
Trong mọi trường hợp, mặc dù tôi vẫn tin rằng COUNT
phiên bản sẽ nhanh hơn trong hầu hết RDBMS, nhưng kết luận của tôi từ thử nghiệm là tôi sẽ tiếp tục SUM(.. 1.. 0..)
trong tương lai, ít nhất là đối với SQL Server không vì lý do nào khác ngoài CẢNH BÁO ANSI được nêu ra khi sử dụng COUNT
.