如何使用户功能确定

时间:2010-01-19 08:45:14

标签: sql sql-server-2008 query-optimization deterministic

我正在尝试基于SQL Server 2008中用户定义函数的确定性行为来实现优化。

在我的测试代码中,我期待没有额外的函数调用dbo.expensive,因为它是确定性的并且使用相同的参数值调用。

我的概念不起作用,请解释原因。 可以做些什么来实现预期的优化?

use tempdb;
go
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.
-- expecting to take about 1 second to execute
create function dbo.expensive(@i int)
returns int with schemabinding
as
begin
 declare @N bigint
 declare @ret bigint
 set @N = 16; -- will generate a set of 2^N
 declare @tab table(num int);

 with multiplicity as
 (
  select 1 as num
  union all
  select m.num + 1 as num from multiplicity m
  where m.num < @N
  union all
  select m.num + 1 as num from multiplicity m
  where m.num < @N
 )
 select @ret = count(num) + @i from multiplicity;
 return @ret;
end

go

declare @tab table(x int);

with manyItems as
(
 select 1 as iterator
 union all
 select iterator + 1 from manyItems
 where iterator < 5
)
insert into @tab select 1 from manyItems;

select CURRENT_TIMESTAMP;
-- expected to take about 1 second
select dbo.expensive(1)

select CURRENT_TIMESTAMP;

-- i want to make this one execute in 1 second too
select x, dbo.expensive(x) as y from @tab;

select CURRENT_TIMESTAMP;

SELECT OBJECTPROPERTY(OBJECT_ID('dbo.expensive'), 'IsDeterministic');

1 个答案:

答案 0 :(得分:1)

如果可能,将您的函数转换为内联的表值UDF(http://msdn.microsoft.com/en-us/library/ms189294.aspx)。

e.g。

create function dbo.expensive2(@N bigint, @i int)
returns table with schemabinding
as
 return
 with multiplicity as
 (
  select 1 as num
  union all
  select m.num + 1 as num from multiplicity m
  where m.num < @N
  union all
  select m.num + 1 as num from multiplicity m
  where m.num < @N
 )
 select count(num) + @i as ret from multiplicity

然后像这样调用它:

select x, (select ret from dbo.expensive2(16, x)) as y from @tab;