我正在使用昂贵的用户定义标量函数调用进行相对复杂的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;
答案 0 :(得分:0)
你永远不会知道。您可以做的一件事是使用计划指南,以帮助优化器保持正确的道路。请参阅Optimizing Queries in Deployed Applications by Using Plan Guides。