SUM() 比 SQL 中的 SELECT() 花费的时间更少。怎么运行的?
SUM() takes less time than SELECT() in SQL. How it works?
我有一个 SQL table 包含 100 万条记录。当我打电话给
SELECT *
FROM [AdventureWorksDW2012].[dbo].[LotTable]
完成查询用了 13 秒。
我 运行 下面的查询获取 ID 列的 SUM()。它包含 运行dom 数字,包含正负值。
SELECT SUM(NewestID)
FROM LotTable
这个查询只用了 500 毫秒。要执行 SUM() SQL 引擎应该读取值并对其应用一些操作。但是如何运行比SELECT()快。背后的逻辑是什么?提前参考以下images.Thanks。
简答(从DBA的角度):
这是因为 SELECT *
必须 return 比 SELECT SUM(NewestID)
更多的列和行。
此外,SUM()
可能 运行 是并行的,这就是它可能更快的原因。
此外,SSMS
中显示的结果集非常慢,为了比较查询的实际执行时间,您可以在会话开始时使用 SET STATISTICS TIME ON
。所以,
SET STATISTICS TIME ON
SELECT *
FROM [AdventureWorksDW2012].[dbo].[LotTable]
SELECT SUM(NewestID)
FROM [AdventureWorksDW2012].[dbo].[LotTable]
现在转到 Messages
选项卡并查看查询的执行时间:
- CPU 时间:在 CPU 上进行的运算,如聚合(
SUM
、AVG
等)或其他算术运算
- 经过时间:CPU时间+存储在RAM中、通过内存总线、网络等发送结果所需的时间
您可以尝试的另一件事是放弃在 SSMS 中显示结果。转到工具 -> 选项 -> 查询结果 -> SQL 服务器 -> 结果到网格并检查 "Discard results after execution".
打开一个新选项卡并再次 运行 您的查询,看看它们的执行时间现在如何比较。 (确保取消选中该选项,以便在新会话的其他选项卡中返回结果)。
实际上,可能有比这些更多的因素,例如,如果您在 NewestID
列上有一个索引,或者您是否有(或没有)在 table 上的聚集索引。
这是预期的行为。你会看到当你向数据库系统发送查询时会发生几件事:
- 分析、优化查询并设计执行模式,
- 查询已执行 (!),
- 将结果传达给客户 (!)
最后两项(带有感叹号)是加速的潜在来源。
首先,如果您总结 个值,您不需要存储所有这些值。事实上,您使用了一个 累加器 。所以一个成熟的数据库系统会用值 0
初始化一个累加器,然后对于它找到的每一行(匹配可选约束),它会将该值添加到累加器。关键是,累加器使用固定数量的内存。例如对于一个整数,通常小于 10 个字节。所以累加器存储在(快速)内存中。
SUM(..)
的一个优点还在于它是关联的:((a+b)+c)+d
等于 (a+b)+(c+d)
。根据数据库的工作和配置方式,它可以将任务分配给几个工作人员,每个工作人员计算 table 的一部分的总和。然后将这些小数加在一起。
另一方面,如果您执行 SELECT
查询,结果将逐行写入。结果是 linear 内存使用:对于匹配的每一行,我们都需要内存。对于大 tables,旧行可能 "swapped" 不在 CPU 缓存中,有时甚至不在内存中。所以执行查询的时间会更长。
系统终于要响应了。现在,如果您执行 SUM(..)
,那只有 一行 。所以传输的数据量很小。 SELECT
查询通常会传输数百行。当然,传输大量数据比传输少量数据需要更多时间。
因为您只使用了 1 个字段和一个函数
我有一个 SQL table 包含 100 万条记录。当我打电话给
SELECT *
FROM [AdventureWorksDW2012].[dbo].[LotTable]
完成查询用了 13 秒。
我 运行 下面的查询获取 ID 列的 SUM()。它包含 运行dom 数字,包含正负值。
SELECT SUM(NewestID)
FROM LotTable
这个查询只用了 500 毫秒。要执行 SUM() SQL 引擎应该读取值并对其应用一些操作。但是如何运行比SELECT()快。背后的逻辑是什么?提前参考以下images.Thanks。
简答(从DBA的角度):
这是因为 SELECT *
必须 return 比 SELECT SUM(NewestID)
更多的列和行。
此外,SUM()
可能 运行 是并行的,这就是它可能更快的原因。
此外,SSMS
中显示的结果集非常慢,为了比较查询的实际执行时间,您可以在会话开始时使用 SET STATISTICS TIME ON
。所以,
SET STATISTICS TIME ON
SELECT *
FROM [AdventureWorksDW2012].[dbo].[LotTable]
SELECT SUM(NewestID)
FROM [AdventureWorksDW2012].[dbo].[LotTable]
现在转到 Messages
选项卡并查看查询的执行时间:
- CPU 时间:在 CPU 上进行的运算,如聚合(
SUM
、AVG
等)或其他算术运算 - 经过时间:CPU时间+存储在RAM中、通过内存总线、网络等发送结果所需的时间
您可以尝试的另一件事是放弃在 SSMS 中显示结果。转到工具 -> 选项 -> 查询结果 -> SQL 服务器 -> 结果到网格并检查 "Discard results after execution".
打开一个新选项卡并再次 运行 您的查询,看看它们的执行时间现在如何比较。 (确保取消选中该选项,以便在新会话的其他选项卡中返回结果)。
实际上,可能有比这些更多的因素,例如,如果您在 NewestID
列上有一个索引,或者您是否有(或没有)在 table 上的聚集索引。
这是预期的行为。你会看到当你向数据库系统发送查询时会发生几件事:
- 分析、优化查询并设计执行模式,
- 查询已执行 (!),
- 将结果传达给客户 (!)
最后两项(带有感叹号)是加速的潜在来源。
首先,如果您总结 个值,您不需要存储所有这些值。事实上,您使用了一个 累加器 。所以一个成熟的数据库系统会用值 0
初始化一个累加器,然后对于它找到的每一行(匹配可选约束),它会将该值添加到累加器。关键是,累加器使用固定数量的内存。例如对于一个整数,通常小于 10 个字节。所以累加器存储在(快速)内存中。
SUM(..)
的一个优点还在于它是关联的:((a+b)+c)+d
等于 (a+b)+(c+d)
。根据数据库的工作和配置方式,它可以将任务分配给几个工作人员,每个工作人员计算 table 的一部分的总和。然后将这些小数加在一起。
另一方面,如果您执行 SELECT
查询,结果将逐行写入。结果是 linear 内存使用:对于匹配的每一行,我们都需要内存。对于大 tables,旧行可能 "swapped" 不在 CPU 缓存中,有时甚至不在内存中。所以执行查询的时间会更长。
系统终于要响应了。现在,如果您执行 SUM(..)
,那只有 一行 。所以传输的数据量很小。 SELECT
查询通常会传输数百行。当然,传输大量数据比传输少量数据需要更多时间。
因为您只使用了 1 个字段和一个函数