【发布时间】:2010-01-15 16:11:49
【问题描述】:
我正在使用昂贵的用户定义标量函数调用进行相对复杂的 CTE 查询。
CTE 的 where 子句过滤了大部分大表数据,返回的结果相对较小,所以如果在结果集上计算,计算昂贵的字段是没有问题的。
如果不评估昂贵的列,SQL 服务器会做得很好,如果 CTE 子查询中的任何谓词都没有触及它,那么它只会针对结果集进行评估。
问题是,在这种情况下,我是否可以依赖优化器的这种良好行为,或者重建计划时可能会出现问题?
这是一个测试代码。
use tempdb;
go
/****** Object: UserDefinedFunction [dbo].[expensive] Script Date: 01/15/2010 18:43:06 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[expensive]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[expensive]
go
-- used to model expensive user defined function.
-- inexpensive in case of @i = 1
create function dbo.expensive(@i int)
returns int
as
begin
if( @i = 1 ) begin return @i; -- inexpensive in this case
end;
declare @N bigint
declare @ret bigint
set @N = 17; -- will generate a set of 2^N
declare @tab table(num int);
with gig as
(
select 1 as num
union all
select g.num + 1 as num from gig g
where g.num < @N
union all
select g.num + 1 as num from gig g
where g.num < @N
)
select @ret = count(num) from gig;
return @ret;
end
go
declare @tab table(i int);
insert into @tab select 1 union select 2 union select 3;
select CURRENT_TIMESTAMP;
with source as
(
-- some really complex stuff that has an expensive calcutated scalar
select c.i, c.caclulated from @tab t
join
(select i, dbo.expensive(i) as caclulated from @tab) as c
on t.i = c.i
)
select * from source where
i = 1; -- this query is inexpensive, because do not touch anything but 1
select CURRENT_TIMESTAMP;
-- this one is expensive
select dbo.expensive(2)
select CURRENT_TIMESTAMP;
【问题讨论】:
-
我收集到您提供的 CTE 是一个示例,而不是您正在使用的真实示例。您能否深入了解真正的 CTE 及其工作原理?你可以发布它的代码吗?你真正想解决什么问题?我可以回答有关执行计划的问题,但我怀疑可能还有其他答案会对您有所帮助。
标签: sql-server query-optimization