2014-04-25 73 views
1

我有兩個(相當複雜的)函數都返回一個表;SQL Server:加入2個查詢,性能問題

(SELECT Id, x, y FROM fnGetXY(3)) (execution takes +/- 5 sec) 

(SELECT Id, a, b FROM fnGetAB(3)) (execution takes +/- 15 sec) 

我想合併結果;

SELECT X.Id, x, y, a, b FROM 
(
(SELECT Id, x, y FROM fnGetXY(3)) X 
JOIN (SELECT Id, a, b FROM fnGetAB(3)) Y ON X.Id=Y.Id 
) 

的結果是正確的,但是這不採取預期的+/- 20-25秒,但90秒。

有什麼辦法可以強制兩個查詢的結果組合的方式消耗的最大值略大於每個的總和?

[更新]

  1. #TEMP;由於這是函數的一部分,不幸的是#temp表不是一個選項。
  2. 我已經試過LEFT JOIN,而不是沒有結果,但似乎FULL OUTER JOIN解決了這一JOIN的情況下..

謝謝大家!

回答

1

在大多數情況下,解決方法是保存中間結果到#TEMP表,然後加入結果:

select Id, x, y 
into #t1 
from fnGetXY(3) 

select Id, a, b 
into #t2 
from fnGetAB(3) 

SELECT #t1.Id, x, y, a, b 
FROM #t1 
INNER JOIN #t2 on #t1.id = #t2.id 

SQL Server優化不喜歡和處理功能十分(除了內嵌TVFs) 。

+1

只是出於好奇,爲什麼要將返回的結果集添加到臨時表? –

+1

出於經驗:)嚴重的是,我必須處理由TVF引起的太多性能問題,這種方法似乎有所幫助。 – dean

+0

我很好奇。我經常發現,在處理非常大的TB大小的數據庫時,使用臨時表存儲中間結果的速度可能比將所有數據全部集中在一起快一個數量級。我可以理解執行計劃人員與大量散列連接等混淆,但它仍然與直覺相反,即一旦數據庫一次可以訪問整個數據,DB就處於最佳狀態,而不是基於循環的方法基本的Java/C#等等。這就像一個小例外。 – Kahn

0

你應該能夠加入這兩個函數,因爲你會加入兩個表,我認爲這些子查詢只是一個相當簡單的查詢矯枉過正。嘗試類似...

SELECT t1.Id 
    , t1.x 
    , t1.y 
    , t2.a 
    , t2.b 
FROM fnGetXY(3) t1 INNER JOIN fnGetAB(3) t2 
ON t1.Id = t2.Id 
+0

嗨,這是我開始的地方,並得到了可怕的性能問題。我希望子查詢會欺騙SQL Server,但沒有什麼區別 – Erik123