2011-01-12 91 views
0

請複製並粘貼以下腳本。使查詢變慢的子查詢

DECLARE @MainTable TABLE(MainTablePkId int) 
INSERT INTO @MainTable SELECT 1 
INSERT INTO @MainTable SELECT 2 

DECLARE @SomeTable TABLE(SomeIdPk int, MainTablePkId int, ViewedTime1 datetime) 
INSERT INTO @SomeTable SELECT 1, 1, DATEADD(dd, -10, getdate()) 
INSERT INTO @SomeTable SELECT 2, 1, DATEADD(dd, -9, getdate()) 
INSERT INTO @SomeTable SELECT 3, 2, DATEADD(dd, -6, getdate()) 

DECLARE @SomeTableDetail TABLE(DetailIdPk int, SomeIdPk int, Viewed INT, ViewedTimeDetail datetime) 
INSERT INTO @SomeTableDetail SELECT 1, 1, 1, DATEADD(dd, -7, getdate()) 
INSERT INTO @SomeTableDetail SELECT 2, 2, NULL, DATEADD(dd, -6, getdate()) 
INSERT INTO @SomeTableDetail SELECT 3, 2, 2, DATEADD(dd, -8, getdate()) 
INSERT INTO @SomeTableDetail SELECT 4, 3, 1, DATEADD(dd, -6, getdate()) 

SELECT m.MainTablePkId, 
     (SELECT COUNT(Viewed) FROM @SomeTableDetail), 
     (SELECT TOP 1 s2.ViewedTimeDetail FROM @SomeTableDetail s2 
               INNER JOIN @SomeTable s1 ON s2.SomeIdPk = s1.SomeIdPk 
               WHERE s1.MainTablePkId = m.MainTablePkId) 
FROM @MainTable m 

此腳本只是一個示例。我有很長的列表SELECT列和子列表中的約12列。在我的From子句中有大約8個表。

要獲取2000條記錄完整查詢需要21秒,如果我刪除子查詢它只需要4秒。

我試圖使用'數據庫引擎優化顧問'來優化查詢,並添加新建議的索引和統計信息,但這些更改使查詢時間更糟糕。

注:

正如我剛纔所說,這是測試數據來解釋我的問題的真實數據有很多表的連接列,但沒有子查詢的結果我們的罰款。

任何幫助謝謝。

+0

不應該SELECT COUNT(查看)FROM @SomeTableDetail需要與表@s的id關聯嗎? – Lamak 2011-01-12 15:44:38

+0

沒有`ORDER BY'的'TOP 1'意味着你會得到任意一行。此外,是否與@MainTable關聯的COUNT()子查詢? – 2011-01-12 15:46:27

+0

在你的第二個子查詢中,你使用了沒有ORDER BY的TOP。你真的想要返回哪個ViewingTimeDetail?最早的?最新的? – 2011-01-12 15:46:39

回答

2

這是一個CTE的例子,它接近你所擁有的但不完全是你想要的,但可以讓你開始。

WITH _CountViewed AS 
(
    SELECT COUNT(Viewed) AS Viewed FROM @SomeTableDetail 
), 
_SomeDate AS 
(
    SELECT MAX(s2.ViewedTimeDetail) As ChangeTime, s1.MainTablePkId FROM @SomeTableDetail s2 
               INNER JOIN @SomeTable s1 ON s2.SomeIdPk = s1.SomeIdPk 
               GROUP BY s1.MainTablePkId 
) 
SELECT sd.MainTablePkId, cv.Viewed, sd.ChangeTime FROM _SomeDate sd 
    OUTER APPLY _CountViewed cv 
2

相關聯的子查詢運行rowili-by-agoniziong-行,你有什麼本質上是在你的過程中很多遊標。將它們更改爲連接(或連接到派生表或CTE)。 使用來自性能標準的相關子查詢是一種不好的做法。它們始終可以用連接,CTE或派生表連接來替換。

0

我正在嘗試在各行之間閱讀並填寫空白處,但我認爲這可能更接近您要完成的內容。

SELECT m.MainTablePkId, SUM(std.Viewed), MAX(std.ViewedTimeDetail) 
    FROM @MainTable m 
     INNER JOIN @SomeTable st 
      ON m.MainTablePkId = st.MainTablePkId 
     INNER JOIN @SomeTableDetail std 
      ON st.SomeIdPk = std.SomeIdPk 
    GROUP BY m.MainTablePkId 
0

,如果他們不正式的PK宣佈我將創建s1.MainTablePkId和m.MainTablePkId,s2.SomeIdPk和s1.SomeIdPk指標。 (已經被sql server索引)

你可以通過添加(nolock)來完成非鎖定讀取,它會通過不鎖定表來加速它。

SELECT m.MainTablePkId, 
     (SELECT COUNT(Viewed) FROM @SomeTableDetail (nolock)), 
     (SELECT TOP 1 s2.ViewedTimeDetail FROM @SomeTableDetail s2 (nolock) 
               INNER JOIN @SomeTable s1 (nolock) ON s2.SomeIdPk = s1.SomeIdPk 
               WHERE s1.MainTablePkId = m.MainTablePkId) 
FROM @MainTable m (nolock)