繁体   English   中英

在建立临时表的TVF上加入连接要比直接子句快得多。 为什么是这样?

Joining on a TVF that builds a temp table is much faster than straight clause. Why is this?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我们正在优化看起来设计不佳的查询。 有一个到多行表值函数的联接,该联接很容易成为内联函数,因此我们对其进行了更新..但是查询变得慢得多。 多行函数返回一个以单列为主键的临时表,而内联TVF刚返回一个直的单列表。

进行一些研发,我们发现使用多行TVF作为子句可以显着提高性能。 以下示例可以在任何数据库上运行,最好具有悠久的对象更新历史。 我们认为第一个查询是最好的设计,但是第二个查询的性能要好得多(通常快20倍)。 这实际上是查询成本,而不是速度

create function udf_ObjectsModifiedBetweenDates
(
    @DateFrom datetime,
    @Dateto datetime
)
returns @t table(object_id int primary key)
as
begin
insert into @t
(
    object_id
)
select object_id
from sys.objects 
where modify_date between @DateFrom and @Dateto
return
end

GO

declare @datefrom datetime = '2017-05-01' --Please adjust these dates to get good sample
declare @dateto datetime = '2018-08-02'

--slow
select object_id, parent_object_id, is_ms_shipped
from sys.objects
where modify_date between @datefrom and @dateto option (recompile)

--fast
select o.object_id, o.parent_object_id, o.is_ms_shipped
from sys.objects o
inner join udf_ObjectsModifiedBetweenDates(@datefrom, @dateto) ombd on o.object_id = ombd.object_id option (recompile)

函数和查询与我们在系统上处理的函数和查询类似,但是在这里我们用系统表代替了用户表。 我们已经在其他用户表上尝试了同样的方法,再次从MTVF中获得了巨大收益。 执行计划表明,在TVF上存在针对较快查询的聚集索引扫描。 谁能解释正在发生的事情,这是否是提高查询性能的可行方法?

在此处输入图片说明

1 个回复

似乎您在执行计划中误将“查询成本(相对于批次)”解释为“查询成本(查询将花费多长时间运行)”。 查询的成本与查询的效率或速度几乎没有关系。

我在以下两个条件上运行了该查询(更改日期):

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

对于标记为“慢”的查询(没有UDF的查询),结果为:

The "slow" one

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 8 ms, elapsed time = 8 ms.

(19305 rows affected)
Table 'sysschobjs'. Scan count 1, logical reads 379, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row affected)

 SQL Server Execution Times:
   CPU time = 62 ms,  elapsed time = 61 ms.

对于标记为“快速”(UDF)的那个,输出为:

The "fast" one

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 7 ms.

(19305 rows affected)
Table 'sysschobjs'. Scan count 0, logical reads 38610, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#B1BBD6DD'. Scan count 1, logical reads 34, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row affected)

 SQL Server Execution Times:
   CPU time = 266 ms,  elapsed time = 329 ms.

从这些统计数据可以看出,到目前为止,非UDF版本是赢家。 非UDF的执行时间快了5倍以上,但是UDF查询的IO太疯狂了(读取次数增加了1000倍以上)。

老实说,多行表值函数通常比性能杀手更重要。 在3种类型的函数(内联表值,标量值和多行表值)中,它们可能是最慢的,而内联通常是最快的。 在传闻中,我听说标量函数在SQL Server 2019中是“更好”的,但是,我还没有进行自我测试,也没有看到任何实际证据。 只是在交谈中。

1 为什么从视图中加入选择的前N个要比仅从视图加入要快得多?

我有一个视图,该视图的未索引列已在另一个查询中加入。 我们无法在视图中创建索引,因为它使用外部联接。 外部查询本质上是: 查询非常慢,通过一些实验,我们发现将查询更改为: 加快查询速度的一个重要因素(10分钟到大约5s)。 该视图仅包含约1000行。 有人可以 ...

5 Mysql子查询比加入快得多

我有以下查询,它们都返回相同的结果和行数: 运行解释扩展,这些是结果: 另一个是: 这些是第二个查询的结果: 第一个需要大约2秒钟,而第二个需要2分钟! 为什么第二个查询需要这么长时间? 我在这里想念的是什么? 谢谢。 ...

7 为什么分配整个Blender数组要比通过迭代分配快得多?

我有两个函数都产生随机噪声,但其中一个需要几秒钟完成,另一个运行在几毫秒。 在硬件方面,差异来自哪里? 当我使用第二个函数时,是否并行执行指令? 或是内存中的整个数组移动到存储图像的相应内存数组? 从随机导入随机 这是我的混合文件的链接 。 我不知道它是否安全。 我可以在Bl ...

8 为什么这个Fibonacci在Python中的评估要比Haskell快得多

我有一个计算第n个Fibonacci数的算法,在Python中它表示为: 在哈斯克尔: 我希望Haskell能够更快地或大约在同一时间进行评估,但是如果使用上面的数字说n = 40,python代码会更快地评估(~x3)。 我正在使用GHCi和Ipython,但我认为这不应该有 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM