2015-10-16 68 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为每个场景生成一个很好的计划而不是试图找到一个适用于所有案例的通用计划。