2013-03-07 55 views
5

我有一個查詢需要2.5秒的FULL JOIN,40秒的INNER,RIGHT或LEFT JOIN。INNER/RIGHT/LEFT JOIN如何比FULL JOIN慢14倍?

這是查詢。子查詢(完成兩次)僅需要1.3秒。

SELECT T1.[time], T1.Total, T1.rn, T2.[time], T2.Total, T2.rn 
FROM 
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn 
FROM 
(
    select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue 
    from LoadTestTransactionSample 
    where LoadTestRunId=285 
    and CounterName='Total Transactions' 
    and TransactionName='Export' 
) foo 
group by [time] 
) T1 
_____ JOIN 
(
select [time], MAX(ComputedValue) as Total, row_number() over (order by [time]) as rn 
FROM 
(
    select SUBSTRING(CONVERT(CHAR(10), IntervalStartTime, 108), 0, 6) as [time], ComputedValue 
    from LoadTestTransactionSample 
    where LoadTestRunId=285 
    and CounterName='Total Transactions' 
    and TransactionName='Export' 
) foo 
group by [time] 
) T2 
ON T1.rn = T2.rn - 1 

select SUBSTRING位是剛開的HH:MM串出一個DateTime的。 LoadTestTransactionSample實際上是一個連接8個表的VIEW。 (僅供參考,數據庫是Visual Studio負載測試結果存儲區)。下面是它的(相關)列:

LoadTestRunId INT NOT NULL 
CounterName NVARCHAR(255) NOT NULL 
TransactionName NVARCHAR(64) NOT NULL 
IntervalStartTime DATETIME NOT NULL 
IntervalEndTime DATETIME NOT NULL 
ComputedValue REAL 

一個完整的JOIN返回一個額外的不必要的行,所以我需要做右連接,以得到正確的答案。

我真的不尋找一個解決方案(我有一個: 預取子查詢到表變量 使用SQL Server 2012的解析函數「LAG」,感謝@ a1ex07),只是一些理解爲到什麼可能會導致這些連接類型之間性能的極端差異。


編輯: 這裏的slow right join query planfast full join query plan。它們太大而不能發佈屏幕截圖。

編輯2: 實際上查詢計劃具有RIGHT JOIN在45%和FULL JOIN在55%,這證明是完全不準確的(實際上它結束了差於99%/ 1%)。我想這意味着我必須依靠實際的執行統計數據。

編輯3: 統計緩慢RIGHT JOIN:

(40 row(s) affected) 
Table 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 37556, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestScenario'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestCase'. Scan count 0, logical reads 176464, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 13411100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 36563718, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterSample'. Scan count 19721, logical reads 269657, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestRunInterval'. Scan count 41, logical reads 205, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 36754 ms, elapsed time = 36763 ms. 

統計快速FULL JOIN:

(41 row(s) affected) 
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterCategory'. Scan count 0, logical reads 1832, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounter'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestScenario'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestCase'. Scan count 0, logical reads 8608, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'WebLoadTestTransaction'. Scan count 0, logical reads 654200, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterInstance'. Scan count 0, logical reads 1783596, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestPerformanceCounterSample'. Scan count 962, logical reads 13154, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'LoadTestRunInterval'. Scan count 2, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 1950 ms, elapsed time = 1944 ms. 

的右連接正在做大量更多的讀取和掃描速度比多儘管有一個明顯類似的查詢計劃,但仍然是FULL JOIN。

工作臺(在FULL JOIN中)提示?這是一個臨時表嗎?

這似乎表明查詢優化器已損壞?

+1

設置你的查詢計劃/顯示統計數據,查看。沒有DDL腳本能夠複製你的模式和數據,任何答案基本上都是猜測。此外,這些性能數字在第一個查詢上與後續查詢不同嗎?這表明您的緩存正在捲入。 – Heather 2013-03-07 23:26:23

+1

我認爲希瑟意味着要求你運行它們1-2-3-4,然後4-3-2-1並比較 – 2013-03-07 23:28:29

+1

而且,每個查詢版本都會在緩存中生成自己的查詢計劃,而這些並不一定同時刷新。這可能會導致偶然的性能難題。 – 2013-03-07 23:30:12

回答

2

好的,事實證明答案是:bad db statistics。很壞。如在,從未更新過。

exec sp_updatestats; FTW。

[隱藏在恥辱頭]

1

這是類似查詢的執行計劃。表格非常小​​。

Execution Plan

查詢1

  • 用途INNER JOIN
  • 執行計劃看起來更小。
  • 但是,佔總時間的62%。

查詢2

  • 用途FULL JOIN
  • 執行計劃看起來很大。
  • 但是,佔總時間的38%。

原因: INNER JOIN在我的情況是使用HASH MATCH。並且FULL JOIN正在使用NESTED LOOP。這是由SQL優化器決定必須使用哪個物理連接(但我們可以使用其他物理連接)。檢查你的執行計劃,這將有所幫助。

+1

您將受益於這些表上的一些索引。 – DaveShaw 2013-03-08 08:12:31

+0

@DaveShaw:是的,這是正確的。 – 2013-03-08 08:22:07

+0

@RaviSingh:奇怪的是,這似乎是查詢計劃不匹配執行!查看我的編輯 - 計劃預計RIGHT JOIN與FULL JOIN的比例爲45%/ 55%,但執行效率爲99%/ 1%。 – agentnega 2013-03-08 20:02:41