2013-10-04 77 views
1

我有一個存儲過程,在WHILE循環中運行幾個查詢,尤其是這些查詢的時間比SP的其他指數長得多,這大大地降低了我的性能。如何用IN替換INNER JOIN?

我讀過幾處使用ININNER JOIN可以提高性能,如果你只是從第一個表中拉列,這正是我正在做的。

但問題是,我沒有第一個線索,我可以用IN子句替換我的INNER JOIN。我得到的概念IN的語法與INNER JOIN有很大不同,但我不知道從哪裏開始。

作爲一個腳註,SQL不是我的強項。所有的建議非常感謝。

下面是其中一個查詢。它們在邏輯上都非常相似。

SELECT @CurrentKey = riv.Key 
FROM ResourceInfo_VW riv 
     INNER JOIN (SELECT Track, 
          Code, 
          [Language] 
        FROM ResourceInfo_VW 
        WHERE Key = @CurrentKey) AS riv2 
     ON riv.Track = riv2.Track 
      AND riv.Code = riv2.Code 
      AND riv.[Language] = riv2.[Language] 
     INNER JOIN UserGroupCourseCatalog_VW ugcc 
     ON riv.Key = ugcc.Key 
WHERE riv.[Type] = 'a' 
     AND ugcc.UserGroupKey = @UserGroupKey 
+3

如果您指定了列,SQL Server會知道您只從第一個表中提取列。如果你使用SELECT *就停止這樣做。 IN不會奇蹟般地改變連接的性能。 –

+3

它可能只是WHILE循環本身會減慢查詢速度。 –

+0

我不好,夥計們。代碼已經啓動。 – Kehlan

回答

0

它花了一點思考,但我通過從相關聲明中刪除所有INNER JOIN來大大優化了此性能。

相對於運行所花費的時間,根據正在處理的記錄數量,此查詢將變得越來越快。

這就是我最終的結果。你會注意到一些額外的變量。這些設置在每個WHILE迭代的開始處。

SELECT @CurrentTrack = Track, 
     @CurrentCode = Code, 
     @CurrentLanguage = [Language] 
FROM ResourceInfo_VW riv 
WHERE riv.Key = @CurrentKey 

SELECT  riv.Key 
FROM  ResourceInfo_VW riv 
WHERE  riv.[Type] = 'a' 
     AND riv.Track = @CurrentTrack 
     AND riv.Code = @CurrentCode 
     AND riv.[Language] = @CurrentLanguage 
     AND riv.CourseKey IN (SELECT CourseKey 
           FROM UserGroupCourseCatalog_VW 
           WHERE UserGroupKey = @UserGroupKey) 
1

是格式有很大的不同,他們在技術上做不同的事情: 這是怎樣一個連接完成:

SELECT * FROM TABLEA a JOIN TABLEB on a.commonfield = b.commonfield 

這是你如何使用報表

SELECT * FROM TABLEA WHERE commonfield in (SELECT commonfield from tableb) 
+2

這更多的是一般性回答IN和JOIN。現在您已經發布了您的代碼,但還有其他一些事情可以想到。保持這一點,這有助於其他人。 – logixologist

+0

感謝您關注我的問題,併發布有用的信息。 +1 – Kehlan

2

一種選擇是創建一個表變量來存儲您的中間結果。

首先在while循環內插入@UserGroupKey s。然後針對您的真實數據表運行一個update ... select。這將是該操作中最昂貴的部分。

表變量現在將查找UserGroupKeyKey,並且應該比搜索原始錶快得多。

declare @t table (UserGroupKey nvarchar(255), Key nvarchar(255)) 
while (...) 
begin 

    insert into @t(UserGroupKey) values (@UserGroupKey) 

end 

-- this is the expensive part, but it only happens once 
update @t 
set Key = riv.KEY 
FROM ResourceInfo_VW riv 
     INNER JOIN (SELECT Track, 
          Code, 
          [Language] 
        FROM ResourceInfo_VW 
        WHERE KEY = @Key) AS riv2 
     ON riv.Track = riv2.Track 
      AND riv.Code = riv2.Code 
      AND riv.[Language] = riv2.[Language] 
     INNER JOIN UserGroupCourseCatalog_VW ugcc 
     ON riv.KEY = ugcc.KEY 
WHERE riv.[Type] = 'a' 
     AND ugcc.UserGroupKey = @t.UserGroupKey 

while (...) 
begin 

    select @Key = Key 
    from @t 
    where @t.UserGroupKey = @UserGroupKey 

end 
+0

表變量是加速的魔術棒。任何時候我都可以用這種方式預處理昂貴的連接,我這樣做。 –

2

那麼我首先注意到的是有一個「相關的子查詢」,這是不需要的。 您已經選擇了變量,即在多個KEY存在的情況下,只有一個值被選中。 在這種情況下,在變量中選擇什麼鍵取決於SQL服務器,因爲沒有order by子句。

考慮添加Top和order by,以便在多行滿足WHERE條件的情況下,將得到什麼結果。 每次運行相同的查詢時,結果應至少保持一致。

我會重寫下面的查詢。如果桌子上有適當的指標,表現應該不錯。

請注意,TOP 1被添加,因爲在該變量中,您無法存儲多個值。因此,找出你想存儲哪一個值。 MIN,MAX,TOP1等。

另外我沒有看到需要做表的自我加入「ResourceInfo_VW」。如果我在這裏錯了,你可以糾正我。

SELECT 
TOP 1 
@Key= riv.KEY 
FROM ResourceInfo_VW riv 
INNER JOIN UserGroupCourseCatalog_VW ugcc 
ON riv.KEY = ugcc.KEY AND riv.[Type] = 'a' 
WHERE ugcc.UserGroupKey = @UserGroupKey 

和公正的注意,如果你試着去了解爲什麼這個查詢是寫在當前這樣的邏輯那麼只有你可以去下一個步驟,你的情況採用不同的運營商,其重寫查詢。

+0

你在做什麼。我只是花了一些時間從我的屁股中抽出我的頭,並檢查自己加入ResourceInfo_VW ......我沒有理由這樣做。我可能不會選擇這個作爲答案,因爲這個問題本身,但非常感謝你打開我的眼睛。 – Kehlan