2010-01-19 2 views
0

Я пытаюсь добиться оптимизации на основе детерминированного поведения, определенной пользователем функции в SQL Server 2008.Как сделать пользовательскую функцию детерминированный

В моем тестовом коде, я жду никаких дополнительных функций не вызывает DBO. дорогой, поскольку он детерминирован и называется с тем же значением аргумента.

Мое понятие не работает, объясните, почему. Что можно сделать для достижения ожидаемой оптимизации?

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

не могли бы вы сохранить эту функцию возвращаемого значения в локальной области действия переменных и назвать его просто один раз? –

+0

Нет, это все еще функция, и это имеет смысл. Я не знаю, что он возвращает, я просто знаю, что он возвращает тот же результат по тому же аргументу во время транзакции. –

+0

Эта функция не использует свой параметр '@ i' - есть ли где-нибудь опечатка? – AakashM

ответ

1

, если это возможно, превратить вашу функцию в инлайн, табличное значение UDF (http://msdn.microsoft.com/en-us/library/ms189294.aspx).

например.

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;