嵌套选择内的昂贵函数

发布于 2024-08-18 17:15:40 字数 1644 浏览 4 评论 0原文

我正在使用昂贵的用户定义标量函数调用进行相对复杂的 CTE 查询。

CTE的where子句过滤了大部分大表数据,并返回相对较小的结果,因此如果在结果集上计算,计算昂贵的字段不是问题。

如果不评估昂贵的列,如果没有被 CTE 子查询内的任何谓词触及,则 SQL Server 做得很好,它仅针对结果集进行评估。

问题是,在这种情况下我可以依赖优化器的这种良好行为,还是重建计划时可能会出现问题?

这是一个测试代码。

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;

I'm doing a relatively complex CTE query with an expensive user defined scalar function call.

The where clauses of the CTE filters most of the large table data, and returns relatively small result, so calculating an expensive field is not a problem, if calculated on the resultset.

SQL server is doing a good job if not evaluating the expensive column, if not touched by any of the predicates inside CTE subqueries, it's evaluated only for the resultset.

The question is, can i rely on this nice behaviour of the optimizer in this case, or things can go wrong when the plan is rebuilt?

Here is a test code.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

意中人 2024-08-25 17:15:40

你永远不会知道。您可以做的一件事是使用计划指南来帮助优化器保持在正确的道路上。请参阅使用计划指南优化已部署应用程序中的查询

You can never know. One thing you can do is to use a plan guide in order to help the optimizer stay on the right path. See Optimizing Queries in Deployed Applications by Using Plan Guides.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文