2011-12-07 58 views
3

我必須優化這個查詢可以幫助我對它進行微調,以便更快地返回數據?在TSQL 2005中優化查詢

目前輸出需要26到35秒左右的時間。我還基於以下附件表創建的索引是我的查詢和索引:

SELECT DISTINCT o.organizationlevel, o.organizationid, o.organizationname, o.organizationcode, 
     o.organizationcode + ' - ' + o.organizationname AS 'codeplusname' 
FROM Organization o 
JOIN Correspondence c ON c.organizationid = o.organizationid 
JOIN UserProfile up ON up.userprofileid = c.operatorid 
WHERE c.status = '4' 
    --AND c.correspondence > 0 
    AND o.organizationlevel = 1 
    AND (up.site = 'ALL' OR 
        up.site = up.site) 
    --AND (@Dept = 'ALL' OR @Dept = up.department) 
    AND EXISTS (SELECT 1 FROM Attachment a 
       WHERE a.contextid = c.correspondenceid 
       AND a.context = 'correspondence' 
       AND (a.attachmentname like '%.rtf' or a.attachmentname like '%.doc')) 
ORDER BY o.organizationcode 

我不能改變任何東西分貝由於權限問題,任何幫助,將不勝感激。

+1

您可以做的最好的事情是「展示計劃」:http://msdn.microsoft.com/en-us/library/ms191227.aspx(注意:該鏈接適用於MSSQL 2008,但大部分是平等的適用於MSSQL 2005)。 – paulsm4

+1

確保這些FK列('c.organizationid'和'c.operatorid')被索引 - 這肯定會有助於JOIN性能 –

+0

我有那些已經索引的列marc_s – aspmvcdeveloper

回答

1

我相信你的頭痛是來自這個部分的具體...就像在哪裏存在可能是你的性能瓶頸。

AND EXISTS (SELECT 1 FROM Attachment a 
      WHERE a.contextid = c.correspondenceid 
      AND a.context = 'correspondence' 
      AND (a.attachmentname like '%.rtf' or a.attachmentname like '%.doc')) 

這可以寫成連接代替。

SELECT DISTINCT o.organizationlevel, o.organizationid, o.organizationname, o.organizationcode, 
    o.organizationcode + ' - ' + o.organizationname AS 'codeplusname' 
FROM Organization o 
JOIN Correspondence c ON c.organizationid = o.organizationid 
JOIN UserProfile up ON up.userprofileid = c.operatorid 
left join article a on a.contextid = c.correspondenceid 
      AND a.context = 'correspondence' 
      and right(attachmentname,4) in ('.doc','.rtf') 

.... 

這消除了喜歡和存在的地方。將where子句放在bottom.it是一個左連接,因此a.anycolumn爲null表示該記錄不存在,並且a.anycolumn不爲null表示找到了一條記錄。其中a.anycolumn不爲null將等同於where存在邏輯中的true。

編輯補充: 又一想你...我不能確定你正在嘗試做的...

AND(up.site =「所有」或 up.site =起來.site)

so where up.site ='All'or 1 = 1?是或真的需要?

並迅速在右邊...右(列,整數)爲您提供字符串右側的字符(我使用了4,因此它將採用指定的列的4個右側字符)。我發現它比一個像聲明運行得快得多。

+0

嗨感謝您的幫助,它的工作速度更快一些,但我想我必須在基於contextid的附件表上編制索引,並且包含(文檔) – aspmvcdeveloper

+0

速度是否足夠快,還是需要更多改進?我不確定是否可以從查詢優化中獲得更多收益,但是可以「預先」執行查詢中某些更密集的部分,例如子字符串函數use ...您缺乏數據庫權限可能會限制某些部分。查看paulsm4在評論中發佈的'show plan'鏈接,並用它來標識查詢的哪一部分是最密集的...一個參考表(ID,布爾值),對於每篇文章都適用'.doc'或'.rtf'的引用比右邊的要快() – Twelfth

+0

heh,閱讀Balam的回答......如果你把他創建的臨時表變成永久的,那麼你可以快速地將它引用爲你需要...只是找到一個可接受的方法來更新這個表(功能上......你正在從查詢的運行時間中刪除時間,並將它移動到插入時保持這個參考表)。 – Twelfth

0

這總是會返回true,這樣就可以消除它(也許是加盟了)

AND (up.site = 'ALL' OR up.site = up.site) 

如果你可以用骯髒的生活與(NOLOCK)

,我會接着讀嘗試將Attachement作爲連接。不禁值得一試。像是相對昂貴,如果它在一個循環中這樣做,一旦它真的有用。

Join Attachment a 
    on a.contextid = c.correspondenceid 
    AND a.context = 'correspondence' 
    AND (a.attachmentname like '%.rtf' or a.attachmentname like '%.doc')) 

我知道有些人堅持認爲存在總是比聯接快。是的,它通常比加入更快,但並非總是如此。

另一種方法是創建使用

CREATE TABLE #Temp (contextid INT PRIMARY KEY CLUSTERED); 
    insert into #temp 
    Select distinct contextid 
    from atachment 
    where context = 'correspondence' 
    AND (attachmentname like '%.rtf' or attachmentname like '%.doc')) 
    order by contextid; 
    go 
    select ... 
    from correspondence c 
    join #Temp 
     on #Temp.contextid = c.correspondenceid 
    go 
    drop table #temp 

特別是一個#temp表如果ProductID等於上對應的主鍵上創建#TEMP的PK將幫助的主鍵或部分。

這樣你就可以確定類似的表達只被評估一次。如果類似的是昂貴的部分,並在一個循環中,那麼它可能會查詢查詢。我在這裏使用了很多,我有一個相當昂貴的核心查詢,我需要這些結果來從多個表中獲取參考數據。如果你多次進行連接,查詢優化器會變得很愚蠢。但是,如果您將查詢優化器PK提供給PK,那麼它不會變得愚蠢並且速度很快。缺點是需要大約0.5秒來創建和填充#temp。

+0

看到更新到我的答案 – Paparazzi

+0

我會#temp與權利(,4)Tewlfth – Paparazzi

+0

非常感謝您的幫助Balam我嘗試臨時表的方法,但它需要更長的時間,所以我不得不採用Tewlfth的方法。 – aspmvcdeveloper