Дорогая функция внутри вложенного выбора - PullRequest
1 голос
/ 15 января 2010

Я делаю относительно сложный запрос CTE с дорогим пользовательским скалярным вызовом функции.

Предложения where в CTE фильтруют большую часть больших данных таблицы и возвращают сравнительно небольшой результат, поэтому вычисление дорогостоящего поля не является проблемой, если оно рассчитывается на основе набора результатов.

Сервер 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 голосов
/ 15 января 2010

Ты никогда не узнаешь. Одна вещь, которую вы можете сделать, это использовать план плана, чтобы помочь оптимизатору оставаться на правильном пути. См. Оптимизация запросов в развернутых приложениях с помощью направляющих планов .

...