SQL查询优化需要20 - 30秒才能运行

时间:2015-10-16 10:33:32

标签: sql sql-server optimization query-optimization

下面的查询需要20秒才能执行,我需要尽可能地优化它。请帮帮我。

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 个答案:

答案 0 :(得分:0)

评论太长了。

ORWHERE条款中的

ON非常难以优化。通常使用这样的查询,最好根据组件构造查询并使用动态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;

您需要为正在使用的所有变量使用类似的逻辑。

答案 1 :(得分: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为每个场景生成一个好的计划,而不是试图找到适用于所有情况的通用计划。

相关问题