【发布时间】:2015-05-26 19:47:39
【问题描述】:
如果我有这样的 sql 语句:
select *
from tableA a
inner join tableB b on dbo.fn_something(a.ColX) = b.ColY
如果您假设 tableA 中有 5 行与 ColX 的值相同,那么 dbo.fn_something() 会以该值调用 5 次还是仅调用一次?
显然,这是一个微不足道的例子,但我感兴趣的是考虑在更复杂的场景中的性能。
更新 感谢@DStanley,根据您的回答,我进一步调查了。在下面的 SQL 上使用带有 SP:StmtStarting 事件的 SQL Profiler 说明了会发生什么。即如您所说:该函数将为联接中的每一行调用一次。
这与原始问题有一个额外的连接。
create table tableA
( id int )
create table tableB
( id_a int not null
, id_c int not null
)
create table tableC
( id int )
go
create function dbo.fn_something( @id int )
returns int
as
begin
return @id
end
go
-- add test data
-- 5 rows:
insert into tableA (id) values (1), (2), (3), (4), (5)
-- 5 rows:
insert into tableC (id) values (101), (102), (103), (104), (105)
-- 25 rows:
insert into tableB (id_a, id_c) select a.id, c.id from tableA a, tableC c
go
-- here dbo.fn_something() is called 25 times:
select *
from tableA a
inner join tableB b on a.id = b.id_a
inner join tableC c on c.id = dbo.fn_something(b.id_c)
-- here dbo.fn_something() is called just 5 times,
-- as the 'b.id_c < 102' happens to be applied first.
-- That's likely to depend on whether SQL thinks it's
-- faster to evaluate the '<' or the function.
select *
from tableA a
inner join tableB b on a.id = b.id_a
inner join tableC c on c.id = dbo.fn_something(b.id_c) and b.id_c < 102
go
drop table tableA ;
drop table tableB;
drop table tableC;
drop function dbo.fn_something;
go
【问题讨论】:
标签: sql sql-server tsql