【问题标题】:How can I improve query performance that blocks other users?如何提高阻止其他用户的查询性能?
【发布时间】:2017-10-19 21:16:00
【问题描述】:

我有一个复杂的子选择语句,它会减慢我的查询速度并阻止其他用户。

select 

                (Case when (Select COUNT(*) from tblQuoteDetails QD where QD.QuoteGUID = a.QuoteGUID) > 1 then
                              (SELECT Round(Sum(dbo.tblQuoteOptions.Premium),2)
                              FROM dbo.tblQuotes AS Q 
                                    INNER JOIN dbo.lstQuoteStatus ON Q.QuoteStatusID = dbo.lstQuoteStatus.QuoteStatusID 
                                    INNER JOIN dbo.tblQuoteOptions ON Q.QuoteGUID = dbo.tblQuoteOptions.QuoteGUID 
                                    --INNER JOIN dbo.tblQuoteOptionPremiums ON dbo.tblQuoteOptionPremiums.QuoteOptionGuid = dbo.tblQuoteOptions.QuoteOptionGUID
                              WHERE     (Q.ControlNo = a.ControlNo) 
                                    AND (Q.OriginalQuoteGUID IS NULL) 
                                    AND (dbo.tblQuoteOptions.Premium <> 0)
                                    AND (DATEDIFF(d,ISNULL(null, dbo.GetEffectiveDate(Q.QuoteGUID)), dbo.GetEffectiveDate(Q.QuoteGUID)) <= 0))
                        Else
                              (SELECT     Round(Avg(dbo.tblQuoteOptions.Premium),2)
                              FROM dbo.tblQuotes AS Q 
                                    INNER JOIN dbo.lstQuoteStatus ON Q.QuoteStatusID = dbo.lstQuoteStatus.QuoteStatusID 
                                    INNER JOIN dbo.tblQuoteOptions ON Q.QuoteGUID = dbo.tblQuoteOptions.QuoteGUID 
                                    --INNER JOIN dbo.tblQuoteOptionPremiums ON dbo.tblQuoteOptionPremiums.QuoteOptionGuid = dbo.tblQuoteOptions.QuoteOptionGUID
                              WHERE     (Q.ControlNo = a.ControlNo) 
                                    AND (Q.OriginalQuoteGUID IS NULL) 
                                    AND (dbo.tblQuoteOptions.Premium <> 0)
                                    AND (DATEDIFF(d,ISNULL(null, dbo.GetEffectiveDate(Q.QuoteGUID)), dbo.GetEffectiveDate(Q.QuoteGUID)) <= 0))
                              --GROUP BY dbo.tblQuoteOptions.QuoteOptionID
                       End) As QuotedPremium
    FROM tblQuotes a

不确定我是否正确阅读了执行计划,但这就是我所看到的:

知道我应该在这里采取什么方法吗?

谢谢

【问题讨论】:

  • 你认为你可以使用temporary tables 吗?
  • 该查询中有很多“中心左侧”的内容。最大的问题是使用标量函数。它们的效率非常低,而且你把它们溅得一地。你有完全没有意义的 isnull 函数,其中第一个值为空。您可能还想看看这篇文章。 sqlblog.com/blogs/aaron_bertrand/archive/2011/09/20/…
  • 注意:使用 GUID 代替复合索引是一种糟糕的策略。特别是如果您对它们应用聚集索引。不要这样做!它不会扩展并且会破坏经历高频率插入、更新和删除操作的系统的性能。
  • 如果您不关心完美的实时数据,那么将一些数据运行到临时表中,然后对临时表执行最终查询可能是加快查询速度的有效方法。请记住,如果基础数据在生成临时表和构建最终输出之间发生变化,您的输出将不会反映它。
  • 您的数据库和正在运行的查询/事务的事务隔离级别是多少? SQL Server 的默认值为Read Committed,读者可以使用此设置阻止写入者。只要你有足够的tempdb 空间/性能,切换到SnapshotRead Committed Snapshot 应该可以缓解“其他人被阻塞”的问题。见stackoverflow.com/q/2741016/1324345

标签: sql-server tsql subquery


【解决方案1】:

另外,部分问题是在 WHERE 子句中使用了 DATEDIFF。

AND (DATEDIFF(d,ISNULL(null, dbo.GetEffectiveDate(Q.QuoteGUID))dbo.GetEffectiveDate(Q.QuoteGUID)) <= 0))

这将严重阻碍优化器的工作。简化这种特殊的比较可能会产生很大的不同。

【讨论】:

    【解决方案2】:

    在不访问您的环境的情况下完全查看查询不会非常有效,但我可以肯定地说,键查找很昂贵,并且通常可以通过确保您从连接表中获取的列是消除的包含在正在使用的索引中。考虑到两个关键查找,我们可以占查询成本的近 80%,我将从那里开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-17
      • 1970-01-01
      • 2013-03-21
      • 1970-01-01
      • 2017-01-21
      • 2013-12-15
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多