2010-09-23 26 views
1

我似乎在SQL將面臨一個奇怪的問題2008年查詢超時的SP,但運行在查詢分析器精細

我有出,如果通過運行運行良好,快速的查詢分析器,但次查詢一個存儲過程!該SP剛剛起步與此查詢,並沒有其他代碼此查詢

SELECT col1,col2 FROM TBL1 (nolock) 
INNER JOIN TBL2 (nolock) 
ON tbl1.col=LEFT(tbl2.col1,LEN(tbl2.col1)-2) AND tbl1.col2=RIGHT(tbl2.col1,2) 
AND tbl1.col4=2233 
AND tbl1.date1 BETWEEN tbl2.date1 and isnull(tbl2.date2,getdate()) 

之前請注意,TBL 1實際上是一個視圖,其中山口和COL2來了通過自連接。同樣根據業務需求,tbl2.col1需要具有連接值。如果需要解決這個問題,我可以修改我的視圖。

+0

這通常是缺少索引或陳舊統計信息的問題。順便說一句,請停止使用'NOLOCK'。 – 2010-09-23 17:45:31

回答

2

作爲一個方面的問題,請注意,如果您可以對字符串長度的一些假設,你的加盟表達可以簡化(並可能獲得更好的性能,因爲一方是現在使用的平等):

SELECT tbl1.col1, tbl1.col2 
FROM 
    TBL1 
    INNER JOIN TBL2 

     ON tbl1.col + tbl1.col2 = tbl2.col1 
     AND tbl1.col4=2233 
     AND tbl1.date1 BETWEEN tbl2.date1 AND Coalesce(tbl2.date2, GetDate()) 

另外,如果你正在尋找最佳的性能,試試這個:

ALTER TABLE TBL2 ADD LeftPart AS (LEFT(col1, LEN(col1)-2)); 
ALTER TABLE TBL2 ADD RightPart AS (RIGHT(tbl2.col1,2)); 
CREATE NONCLUSTERED INDEX IX_TBL2_Parts ON TBL2 (LeftPart, RightPart); 

現在你只需加入像這樣:

SELECT tbl1.col1, tbl1.col2 
FROM 
    TBL1 
    INNER JOIN TBL2 
     ON tbl1.col = tbl2.LeftPart 
     AND tbl1.col2 = tbl2.RightPart 
     AND tbl1.col4=2233 
     AND tbl1.date1 BETWEEN tbl2.date1 AND Coalesce(tbl2.date2, GetDate()) 

甚至更​​好,更改數據庫設計以實際將TBL2.col1數據存儲在兩列中。通過在一列中放入兩個截然不同的數據,您違反了第一種正常形式,現在,正如您發現的那樣,您在整個應用程序中支付性能,開發&10維護時間,查詢複雜性和等等。

甚至可以將我的方案顛倒過來以便LeftPart和RightPart列是實數,並且創建一個具有Col1名稱的新計算列,並使用索引來實現這些值並使它們可供搜索。最後,如果完全需要,您可以重命名錶,使用舊名稱在表上創建視圖,然後在視圖上放置INSTEAD-OF觸發器,以截取對該表的數據操作並將它們轉換爲正確的模式。

更新

順便說一句,如果你對錶的設計沒有任何影響,你可能要考慮使用的「99991231」的tbl2.date2的「開放式日期」值或一些這樣的,而不是空值。 Coalesce可能會導致性能下降,有時會在可能的情況下強制進行掃描。

+0

您的意見和建議是非常有效的,理想情況下,我嘗試使用語法,如ON tbl1.col + tbl1.col2 = tbl2.col1,並按照您的建議在左側和右側添加索引但無法執行,因爲tbl2實際上是一個VIEW,並且VIEW在表上自加入生成左列和右列我猜自己加入的視圖不能有索引:( – 2010-09-24 00:34:56

+0

因爲我不能在tbl2上有索引,所以ON tbl1.col + tbl1.col2 = tbl2.col1因爲甚至比我當前的語法慢得多最後,我不能將左右兩部分原本存儲在單獨的列中,因爲這是我的具體業務需求,所以我很迷茫:/ – 2010-09-24 00:37:19

+0

另一方面,從您的建議我添加了兩個計算列到我的TBL2添加左和右計算列。而查詢似乎現在在SP工作!現在完全嘗試。如果它工作,將回發。 – 2010-09-24 01:24:30

1

我遇到過類似的情況,是由parameter sniffing造成的。您可以嘗試上面的文章中討論的方法,看看它是否有所作爲。

會發生什麼情況是,當您首次運行存儲過程時,SQL Server將緩存它的執行計劃並將其用於前進。如果使用使這個執行計劃不是最佳的參數運行存儲過程,可以看到您描述的行爲。

您也可以使用查詢提示recompile來確保它在每次執行時都使用新的執行計劃。要做到這一點,你會增加OPTION(RECOMPILE)到您的查詢的末尾:

SELECT id, name 
from tableName 
WHERE id between @min and @max 
OPTION(RECOMPILE); 

This link越過該參數嗅探問題的幾種解決方案。

+0

添加選項(重新編譯)沒有幫助:(閱讀您提到的文章 – 2010-09-23 18:31:26

+0

'選項(重新編譯)'真的有助於日期操作 – 2010-09-23 18:32:44