简体   繁体   English

查询执行需要花费太多时间

[英]Query execution takes too much time

I have the following query 我有以下查询

SELECT dbo.tblRegion.RegionName,
       dbo.tblDistributionLocation.DistributionLocationName,
       dbo.tblTSA.TSAName,
       TEmailInfo.EmailCM,
       COUNT(*) AS EmailCount
FROM   dbo.tblArea
       INNER JOIN dbo.tblTerritory
         ON dbo.tblArea.AreaID = dbo.tblTerritory.AreaID
       INNER JOIN dbo.tblDistribution
         ON dbo.tblTerritory.TerritoryID = dbo.tblDistribution.TerritoryID
       INNER JOIN dbo.tblDistributionLocation
         ON dbo.tblDistribution.DistributionID = dbo.tblDistributionLocation.DistributionID
       INNER JOIN dbo.tblRegion
         ON dbo.tblArea.RegionID = dbo.tblRegion.RegionID
       INNER JOIN dbo.tblTSA
         ON dbo.tblDistributionLocation.DistributionLocationID = 
                                                       dbo.tblTSA.DistributionLocationID
       INNER JOIN dbo.tblTSAEmail
         ON dbo.tblTSA.TSAID = dbo.tblTSAEmail.TSAID
       INNER JOIN (SELECT *
                   FROM   dbo.tblCMEvalEmail
                   WHERE  ( dbo.tblCMEvalEmail.EmailSentDate 
                    BETWEEN '2013-05-19 00:00:00' AND '2013-06-16 23:59:59' )) AS TCMEvalEmail
         ON dbo.tblTSAEmail.TSAEmail = TCMEvalEmail.EmailSenderEmail
       INNER JOIN (SELECT *
                   FROM   dbo.tblCMEvalEmailInfo
                   WHERE  dbo.tblCMEvalEmailInfo.EmailCMFacingDate 
                    BETWEEN '2013-05-19 00:00:00' AND '2013-06-16 23:59:59') AS TEmailInfo
         ON TCMEvalEmail.EmailID = TEmailInfo.EmailID
WHERE  ( dbo.tblTSA.TSAActive = 1 )
       AND TCMEvalEmail.EmailStatus = 'Success'
GROUP  BY dbo.tblRegion.RegionName,
          dbo.tblDistributionLocation.DistributionLocationName,
          dbo.tblTSA.TSAName,
          TEmailInfo.EmailCM 

What's wrong with this query that it takes so much time? 这个查询有什么问题需要花费这么多时间?

But if I shorten time '2013-05-20 00:00:00' and '2013-06-16 23:59:59' then it replies so quick. 但如果我缩短'2013-05-20 00:00:00'和'2013-06-16 23:59:59'的时间,那么它回复得那么快。 What's problem with my query that it takes so much time? 我的查询有什么问题需要花费这么多时间?

Performance tuning is not just flipping a magic switch - it's hard work. 性能调整不只是翻转魔术开关 - 这很难。

So start with the most obvious : try to reduce your query to the absolute minimum. 所以从最明显的开始:尝试将查询减少到绝对最小值。

Eg 例如

  • why are you selecting SELECT * in your inner queries, when you're only ever using a single (or two) columns from that data? 当您只使用该数据中的单个(或两个)列时,为什么要在内部查询中选择SELECT * Only select what you really need ! 只选择你真正需要的东西

In the first case, if I'm not mistaken, you only ever need the EmailSenderEMail column - so select only that! 在第一种情况下,如果我没有弄错,你只需要EmailSenderEMail列 - 所以只选择它!

INNER JOIN 
(
   select EmailSenderEmail 
   from dbo.tblCMEvalEmail 
   where (dbo.tblCMEvalEmail.EmailSentDate BETWEEN '2013-05-19 00:00:00' 
                                               AND '2013-06-16 23:59:59') 
) as TCMEvalEmail  ON dbo.tblTSAEmail.TSAEmail = TCMEvalEmail.EmailSenderEmail 

In the second case, you need the EmailID for the JOIN, and the EmailCM in the output of the SELECT - so select only those two columns! 在第二种情况下,你需要的EmailID中JOIN和EmailCM在输出SELECT -只所以选择这两列!

INNER JOIN 
(
    select EMailID, EMailCM
    from dbo.tblCMEvalEmailInfo 
    where dbo.tblCMEvalEmailInfo.EmailCMFacingDate BETWEEN '2013-05-19 00:00:00' 
                                                       and '2013-06-16 23:59:59'
 ) as TEmailInfo ON TCMEvalEmail.EmailID = TEmailInfo.EmailID 
  • next step: make sure you have the appropriate indexes in place. 下一步:确保您具有适当的索引。 If you have subselects like these, it's extremely valuable to have an index that will cover your query , eg that will return exactly those columns you need. 如果您有这样的子选择,那么拥有一个覆盖您的查询的索引是非常有价值的,例如,它将准确返回您需要的列。 So do you have an index on dbo.tblCMEvalEmail with the EmailSenderEMail column? 那么你有一个带有EmailSenderEMail列的dbo.tblCMEvalEmail索引吗? Do you have an index on dbo.tblCMEvalEmailInfo that contains the two columns EMailID, EMailCM ? 你有一个关于dbo.tblCMEvalEmailInfo的索引,它包含两列EMailID, EMailCM吗?

  • another thing: all foreign key columns should be indexed, to improve the speed of JOIN operations, and to help speed up foreign key constraint checks. 另一件事:所有外键列都应该被索引,以提高JOIN操作的速度,并帮助加快外键约束检查。 Are you foreign keys used here all indexed? 你这里使用的外键都是索引的吗?

Probably don't have the proper indexes to do the joins. 可能没有适当的索引来进行连接。 You could optimize out the two subselects, but I suspect the query optimizer is doing that already. 您可以优化两个子选择,但我怀疑查询优化器已经这样做了。

SELECT dbo.tblRegion.RegionName, 
        dbo.tblDistributionLocation.DistributionLocationName, 
        dbo.tblTSA.TSAName,
        TEmailInfo.EmailCM,
        COUNT(*) as EmailCount
FROM dbo.tblArea 
INNER JOIN dbo.tblTerritory
 ON dbo.tblArea.AreaID = dbo.tblTerritory.AreaID
INNER JOIN dbo.tblDistribution
 ON dbo.tblTerritory.TerritoryID = dbo.tblDistribution.TerritoryID
INNER JOIN dbo.tblDistributionLocation
 ON dbo.tblDistribution.DistributionID = dbo.tblDistributionLocation.DistributionID 
INNER JOIN dbo.tblRegion
 ON dbo.tblArea.RegionID = dbo.tblRegion.RegionID 
INNER JOIN dbo.tblTSA
 ON dbo.tblDistributionLocation.DistributionLocationID = dbo.tblTSA.DistributionLocationID 
INNER JOIN dbo.tblTSAEmail
 ON dbo.tblTSA.TSAID = dbo.tblTSAEmail.TSAID 
INNER JOIN dbo.tblCMEvalEmail
 ON dbo.tblTSAEmail.TSAEmail = tblCMEvalEmail.EmailSenderEmail
   AND dbo.tblCMEvalEmail.EmailSentDate BETWEEN '2013-05-19 00:00:00' 
                                               AND '2013-06-16 23:59:59'
   AND tblCMEvalEmail.EmailStatus='Success'
INNER JOIN dbo.tblCMEvalEmailInfo
 ON tblCMEvalEmail.EmailID = tblCMEvalEmailInfo.EmailID
   AND dbo.tblCMEvalEmailInfo.EmailCMFacingDate BETWEEN '2013-05-19 00:00:00' 
                                                       and '2013-06-16 23:59:59'
WHERE (dbo.tblTSA.TSAActive = 1) 
GROUP BY dbo.tblRegion.RegionName, 
          dbo.tblDistributionLocation.DistributionLocationName, 
          dbo.tblTSA.TSAName, TEmailInfo.EmailCM

As marc_s points out, optimization is not a quick thing to do, nor is it a one-trick-fixes-all solution. 正如marc_s指出的那样,优化不是一件容易的事情,也不是一个单一的技巧 - 解决方案。 Your best bet is to read up on the topic (see http://beginner-sql-tutorial.com/sql-query-tuning.htm for some starter tips). 您最好的选择是阅读该主题(有关初学者提示,请参阅http://beginner-sql-tutorial.com/sql-query-tuning.htm )。

You should also read up on the EXPLAIN PLAN tool (or equivalent variation for your DB) which is a vital optimisation tool; 您还应该阅读EXPLAIN PLAN工具(或数据库的等效变体),这是一个至关重要的优化工具; it will highlight things that can be slowing down your query on your particular database, like full table scans - eliminating these typically gives you quick wins and often a noticable improvement. 它将突出显示可能会减慢您对特定数据库的查询速度的事情,例如全表扫描 - 消除这些通常会让您快速获胜并且通常会有明显的改进。

Just off the bat though, the two things that jumps out at me are: 尽管如此,我突然发现的两件事是:

  1. Do you have indices set up on all the IDs you're using to join? 您是否在所有要加入的ID上设置了索引? If not, this will have a negative hit on performance 如果没有,这将对性能产生负面影响
  2. TCMEvalEmail.EmailStatus='Success' is a string match which is typically a slow comparison to do; TCMEvalEmail.EmailStatus ='Success'是一个字符串匹配,通常是一个缓慢的比较; without seeing the results of your Explain Plan it's hard to say, but you might want to consider replacing this with a numeric status code (eg a Foreign Key to a STATUS table) - but since this could be a big task you should only do it if Explain Plan highlights it as an issue. 没有看到你的解释计划的结果很难说,但你可能想考虑用数字状态代码(例如STATUS表的外键)替换它 - 但是因为这可能是一个大任务你应该只做它如果解释计划强调它是一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM