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魔法吗?
答案 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子句中实际列选择的内容 - 请提供这些详细信息,因为无法在不真正知道查询的情况下分析查询 - 令人难以忍受的细节 - 因为性能问题总是存在于细节。