嵌套选择中的昂贵功能

时间:2010-01-15 16:11:49

标签: sql-server query-optimization

我正在使用昂贵的用户定义标量函数调用进行相对复杂的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;

1 个答案:

答案 0 :(得分:0)

你永远不会知道。您可以做的一件事是使用计划指南,以帮助优化器保持正确的道路。请参阅Optimizing Queries in Deployed Applications by Using Plan Guides