2015-10-16 83 views
0

下面的查詢需要20秒來執行,我需要儘可能多地優化它。請幫助我。需要20 - 30秒才能運行的SQL查詢優化

SELECT Distinct 
    qh.QuoteHeaderId, [dbo].[mpx2_Get_PhoneGrade](qh.QuoteHeaderId) 
FROM 
    t_QuoteHeader QH 
INNER JOIN 
    t_HandsetQuote h ON Qh.QuoteHeaderId = h.QuoteHeaderId 
INNER JOIN 
    t_phoneAudit P ON ISNULL(h.InspectionPhoneAuditId, h.QuotePhoneAuditId) = p.PhoneAuditId   
INNER JOIN 
    mpx2_vw_customers C ON qh.CustomerId = C.CustomerId 
INNER JOIN 
    @ContactChannels CC ON C.ContactChannelId = CC.ContactChannelId 
LEFT OUTER JOIN 
    t_HandsetQuoteAdditionalInfo_TRNX hqa ON hqa.hqid = h.HandsetQuoteId 
WHERE 
    ((@VirtualStatusId = 0 OR @VirtualStatusId = -2 OR 
     C.ContactChannelId NOT IN (1, 2, 13, 80)))   
    AND ((@VirtualStatusId = -2) OR 
     ('Q'+ CAST(Qh.QuoteStatusId AS VARCHAR(3)) + 'S' + CAST(h.StockStatusId AS VARCHAR(3)) IN 
      (SELECT 'Q'+ CAST(QuoteStatusId AS VARCHAR(3)) + 'S' + CAST(StockStatusId AS VARCHAR(3)) FROM t_VirtualStatusMap WHERE (@VirtualStatusId IS NULL OR @VirtualStatusId IN (0,-1) OR VirtualStatusId = @VirtualStatusId)) 
     ) 
    ) 
    AND ((qh.IsCancelled = 0 and @onlyOpenOrders = 1) OR @onlyOpenOrders = 0) 
    AND ((h.IsCancelled = 0 and @onlyOpenOrders = 1) OR @onlyOpenOrders = 0)   
    AND (qh.ConfirmedDate <= @CutOff) 

請幫我優化它。此查詢用於存儲過程。

Execution plan

+2

如何在不知道數據庫結構或者查看查詢計劃的情況下提供幫助? – DavidG

+0

對不起,但我必須上傳執行計劃 – HarshSharma

+0

只需[編輯]問題。 – DavidG

回答

0

這是太長了評論。

OR s在WHEREON子句很難優化。通常使用這樣的查詢,最好基於組件構建查詢並使用動態SQL。

例如,在@OnlyOpenOrders條件將包括如下:

declare @sql varchar(max); 
set @sql = ' . . .'; 
declare @where varchar(max); 

set @where = 'where . . .'; 

if (@OnlyOpenOrders = 0) begin 
    set @where = @where + ' and qh.IsCancelled = 0 and h.IsCancelled = 0' 
end; 

set @sql = @sql + ' ' + @where; 

exec sp_executesql @sql; 

你需要有類似的邏輯,你正在使用的所有變量。

+0

或使用UNION子句 –

+0

@SteveFord編寫查詢。 。 。這是一種可能性,但是當你有多個條件時,「UNION ALL」會變得複雜。 –

0

有幾件事情,雖然其他人已經說沒有所有必要的信息,如完整的執行計劃,所涉及的表的模式,它主要是準則/猜測;

1.)在這部分,它會出現你從QuoteStatusId和StockStatusId建立一個字符串,以便比較它們; ('Q'+ CAST(Qh.QuoteStatusId AS VARCHAR(3)) + 'S' + CAST(h.StockStatusId AS VARCHAR(3)) IN (SELECT 'Q'+ CAST(QuoteStatusId AS VARCHAR(3)) + 'S' + CAST(StockStatusId AS VARCHAR(3)) FROM t_VirtualStatusMap WHERE (@VirtualStatusId IS NULL OR @VirtualStatusId IN (0,-1) OR VirtualStatusId = @VirtualStatusId))) 如果您跳過構建字符串,因爲它們由相同的兩列組成,並且直接比較兩列可能會加快速度。

2.)你有沒有試過在你附加的圖片中添加它所建議的索引?在沒有看到你的模式和執行計劃的情況下,很難建議合適的模式,但可能值得添加一個建議(右鍵單擊綠色文字,它會生成添加建議索引的代碼)。我會閱讀索引並確保查詢使用適當的索引。 ConfirmedDate看起來像一個明顯的,以及所有的連接鍵。 3.如Gordon建議使用動態sql,或者如果您對此不滿意 - 可能將查詢拆分爲幾個查詢並使用IF語句在每個查詢之間切換,可幫助SQL爲每個場景生成一個很好的計劃而不是試圖找到一個適用於所有案例的通用計劃。