我正在尝试基于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');
答案 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;