我有以下查询
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
这个查询有什么问题需要花费很多时间?
但如果我缩短'2013-05-20 00:00:00'和'2013-06-16 23:59:59'的时间,那么它回复得那么快。我的查询有什么问题需要花费这么多时间?
答案 0 :(得分:2)
性能调整不只是翻转魔术开关 - 这很难。
首先从最明显的开始:尝试将查询减少到绝对最小值。
E.g。
SELECT *
?只选择真正需要的!在第一种情况下,如果我没有弄错,你只需要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
在第二种情况下,您需要加入EmailID
,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
下一步:确保您有适当的索引。如果你有这样的子选择,那么拥有一个覆盖你的查询的索引是非常有价值的,例如:这将完全返回您需要的列。那么,dbo.tblCMEvalEmail
列的EmailSenderEMail
列上有索引吗?您是否在dbo.tblCMEvalEmailInfo
上有一个包含两列EMailID, EMailCM
的索引?
另一件事:所有外键列都应编入索引,以提高JOIN操作的速度,并帮助加快外键约束检查。你在这里使用的外键都是索引的吗?
答案 1 :(得分:0)
可能没有适当的索引来进行连接。您可以优化这两个子选择,但我怀疑查询优化器已经这样做了。
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
答案 2 :(得分:0)
正如marc_s指出的那样,优化不是一件容易的事情,也不是一个单一的技巧 - 解决方案。您最好的选择是阅读相关主题(有关初学者提示,请参阅http://beginner-sql-tutorial.com/sql-query-tuning.htm。)
您还应该阅读EXPLAIN PLAN工具(或数据库的等效变体),这是一个至关重要的优化工具;它会突出显示可能会减慢您对特定数据库的查询速度的事情,例如全表扫描 - 消除这些通常会让您快速获胜并且通常会有明显的改进。
然而,刚开始,我跳出来的两件事是: