【发布时间】:2022-01-26 16:35:13
【问题描述】:
为什么使用数字表比使用递归 CTE 动态生成它们要快得多?
在我的机器上,给定一个表numbers,其中包含一列n(主键),其中包含从1 到100000 的数字,以下查询:
select n from numbers;
大约需要 400 毫秒才能完成。
使用递归 CTE 生成数字 1 到 100000:
with u as (
select 1 as n
union all
select n + 1
from u
where n < 100000
)
select n
from u
option(maxrecursion 0);
在 SQL Server 2019 上都需要大约 900 毫秒才能完成。
我的问题是,为什么第二个选项比第一个慢很多?第一个不是从磁盘获取结果,因此应该更慢吗?
否则,有什么方法可以让 CTE 运行得更快?因为在我看来,这是一个比在数据库中存储数字列表更优雅的解决方案。
【问题讨论】:
-
简单,SQL Server 引擎针对基于集合的操作进行了优化,而不是递归操作。
-
@shawnt00 将第二个示例编辑为
u而不是numbers以避免混淆。我试过了,它仍然需要同样的时间。 -
我总是想知道为什么人们反对创建表 - 存储需求几乎立即收回成本,因为如果表被足够频繁地读取(而且应该如此!)它总是在内存中。内存相当快。另见this question。
-
在实用程序数据库中存储几百个 8k 页面,以供服务器上多个数据库上的任意数量查询重复使用,并且可以在几毫秒内读取,而 CPU 可忽略不计,而不是重复相同的昂贵 CPU 周期在每次调用时生成相同的列表,尤其是在为云中的 CPU 收费时....我知道我认为最小的方法!
标签: sql sql-server tsql