我根据您的模式创建了表big_table
create table big_table
(
updatetime datetime not null,
name char(14) not null,
TheData float,
primary key(Name,updatetime)
)
然后,我用该代码填充了50,000行的表:
DECLARE @ROWNUM as bigint = 1
WHILE(1=1)
BEGIN
set @rownum = @ROWNUM + 1
insert into big_table values(getdate(),'name' + cast(@rownum as CHAR), cast(@rownum as float))
if @ROWNUM > 50000
BREAK;
END
然后,我使用SSMS测试了这两个查询,并意识到在第一个查询中您正在寻找TheData的最大值,在第二个查询中正在寻找updatetime的最大值。
因此,我修改了第一个查询,以获取更新时间的最大值
set statistics time on -- execution time
set statistics io on -- io stats (how many pages read, temp tables)
-- query 1
SELECT MAX([UpdateTime])
FROM big_table
-- query 2
SELECT MAX([UpdateTime]) AS value
from
(
SELECT [UpdateTime]
FROM big_table
group by [UpdateTime]
) as t
set statistics time off
set statistics io off
使用统计时间,我获得了解析,编译和执行每个语句所需的毫秒数
使用Statistics IO,我可以获得有关磁盘活动的信息
统计时间和统计IO提供有用的信息。例如使用的临时表(由工作表指示)。还读取了多少逻辑页,这些逻辑页指示从缓存读取的数据库页数。
然后,我使用CTRL + M激活执行计划(激活显示实际的执行计划),然后使用F5执行。
这将提供两个查询的比较。
这是“ 消息”选项卡的输出
-查询1
表'big_table'。扫描计数1,逻辑读543,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
SQL Server执行时间:
CPU时间= 16毫秒,经过的时间= 6毫秒。
-查询2
表“ 工作台 ”。扫描计数0,逻辑读0,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
表'big_table'。扫描计数1,逻辑读543,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
SQL Server执行时间:
CPU时间= 0毫秒,经过的时间= 35毫秒。
这两个查询都进行543次逻辑读取,但是第二个查询的经过时间为35ms,其中第一个查询只有6ms。您还将注意到,第二个查询导致使用tempdb中的临时表,由单词worktable指示。即使工作表的所有值都为0,工作仍在tempdb中完成。
然后是“消息”选项卡旁边的实际执行计划选项卡的输出
根据MSSQL提供的执行计划,您提供的第二个查询的总批处理成本为64%,而第一个查询仅占总批处理成本的36%,因此第一个查询所需的工作较少。
使用SSMS,您可以测试和比较查询,并准确了解MSSQL如何解析查询以及哪些对象:表,索引和/或统计信息(如果有的话)用于满足这些查询。
测试时要记住的另一点说明是,如果可能的话,在测试之前清除缓存。这有助于确保比较准确,这在考虑磁盘活动时很重要。我首先使用DBCC DROPCLEANBUFFERS和DBCC FREEPROCCACHE清除所有缓存。请注意不要在实际使用的生产服务器上使用这些命令,因为您将有效地迫使服务器将所有内容从磁盘读取到内存中。
这是相关的文档。
- 使用DBCC FREEPROCCACHE清除计划缓存
- 使用DBCC DROPCLEANBUFFERS清除缓冲池中的所有内容
根据使用环境的方式,可能无法使用这些命令。
更新10/28 12:46 pm
对执行计划图像和统计信息输出进行了更正。
getdate()
跳出循环