นี่คือการทดสอบของฉันใน 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
ดูที่การวิ่งเดี่ยวและแบทช์แยกกัน
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
ผลลัพธ์หลังจากใช้งาน 5 ครั้ง (และซ้ำ) ค่อนข้างไม่สามารถสรุปได้
which ** Individual
----- ----------- ----------- -----------
0 93600 187201 103927
1 93600 187201 103864
which ** Batch
----- ----------- ----------- -----------
0 10108817 10545619 10398978
1 10327219 10498818 10386498
มันแสดงให้เห็นว่ามีความแปรปรวนในสภาพการทำงานมากกว่าความแตกต่างระหว่างการนำไปใช้งานเมื่อวัดด้วยความละเอียดของตัวจับเวลา SQL Server ทั้งสองเวอร์ชันสามารถอยู่ด้านบนและความแปรปรวนสูงสุดที่ฉันเคยได้รับคือ 2.5%
อย่างไรก็ตามการใช้วิธีที่แตกต่าง:
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]))
จากการอ่านของฉันดูเหมือนว่าเวอร์ชั่น SUM จะทำอะไรได้มากกว่านี้อีกเล็กน้อย กำลังดำเนินการ COUNT นอกเหนือจาก SUM ต้องบอกว่าCOUNT(*)
แตกต่างและควรจะเร็วกว่าCOUNT([Expr1004])
(ข้าม NULLs ตรรกะมากขึ้น) เครื่องมือเพิ่มประสิทธิภาพที่เหมาะสมจะทราบว่า[Expr1004]
ในSUM([Expr1004])
รุ่น SUM เป็นประเภท "int" และใช้ประโยชน์จากการลงทะเบียนจำนวนเต็ม
ไม่ว่าในกรณีใดในขณะที่ฉันยังเชื่อว่าCOUNT
รุ่นจะเร็วขึ้นใน RDBMS ส่วนใหญ่ข้อสรุปของฉันจากการทดสอบคือฉันจะไปด้วยSUM(.. 1.. 0..)
ในอนาคตอย่างน้อยสำหรับ SQL Server โดยไม่มีเหตุผลอื่นนอกจาก ANSI WARNINGS เมื่อใช้งานCOUNT
.