调用T-SQL表值函数比调用一次快多倍?

时间:2016-06-02 22:57:45

标签: sql-server tsql

我很困惑。我正在使用T-SQL并尝试优化看起来像这样的代码:

SELECT * FROM MyTable mt
LEFT JOIN
  (SELECT * FROM Table1 t1
   LEFT JOIN api.tableValuedFunc(@someArgs) tvf
   on tvf.Key = t1.Key) firstJoin
on mt.Key = firstJoin.key
LEFT JOIN
  (SELECT * FROM Table2 t2
   LEFT JOIN api.tableValuedFunc(@someArgs) tvf
   on tvf.Key = t2.Key) secondJoin
on mt.Key = secondJoin.key

通过这样做:

declare @tvfResult TABLE ( ... some columns ... )
insert into @tvfResults SELECT * FROM api.tableValuedFunc(@someArgs);

SELECT * FROM MyTable mt
LEFT JOIN
  (SELECT * FROM Table1 t1
   LEFT JOIN @tvfResults tvf
   on tvf.Key = t1.Key) firstJoin
on mt.Key = firstJoin.key
LEFT JOIN
  (SELECT * FROM Table2 t2
   LEFT JOIN @tvfResults tvf
   on tvf.Key = t2.Key) secondJoin
on mt.Key = secondJoin.key

这使执行时间加倍!为什么是这样?在第二个例子中,我(天真地)假设我经常执行一半的函数。在我破坏的幕后会发生某种SQL魔法吗?

2 个答案:

答案 0 :(得分:1)

创建本地临时表而不是创建表变量,如果它输出大量行,可能会有更好的性能。

create table #tvfResult  ( ... some columns ... )

insert into #tvfResults SELECT * FROM api.tableValuedFunc(@someArgs);

SELECT * FROM MyTable mt
LEFT JOIN
  (SELECT * FROM Table1 t1
   LEFT JOIN #tvfResults tvf
   on tvf.Key = t1.Key) firstJoin
on mt.Key = firstJoin.key
LEFT JOIN
  (SELECT * FROM Table2 t2
   LEFT JOIN #tvfResults tvf
   on tvf.Key = t2.Key) secondJoin
on mt.Key = secondJoin.key

本地临时表在与SQL Server实例相同的连接期间仅对其创建者可见,就像首次创建或引用表时一样。用户断开与SQL Server实例的连接后,将删除本地临时表。

如果要使用相同的会话重新运行查询,请显式删除临时表。

drop table #tvfResult

答案 1 :(得分:0)

请注意,除非您从问题中省略了几个关键因素,否则您的第一个查询将简化为:

SELECT * FROM MyTable mt
LEFT JOIN Table1 t1 on mt.Key = t1.key
LEFT JOIN Table2 t2 on mt.Key = t2.key
LEFT JOIN api.tableValuedFunc(@someArgs) tvf1 on tvf1.Key = t1.key
LEFT JOIN api.tableValuedFunc(@someArgs) tvf2 on tvf2.Key = t2.key

现在,分析简化为SELECT子句中实际列选择的内容 - 请提供这些详细信息,因为无法在不真正知道查询的情况下分析查询 - 令人难以忍受的细节 - 因为性能问题总是存在于细节。