Sql 查询执行时间太长
我有以下疑问Sql 查询执行时间太长,sql,sql-server-2008,Sql,Sql Server 2008,我有以下疑问 SELECT dbo.tblRegion.RegionName, dbo.tblDistributionLocation.DistributionLocationName, dbo.tblTSA.TSAName, TEmailInfo.EmailCM, COUNT(*) AS EmailCount FROM dbo.tblArea INNER JOIN dbo.tblTerritory ON
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”的时间,那么它的回复速度会很快。我的查询花了这么多时间,有什么问题吗?性能调整不仅仅是打开一个神奇的开关,而是一项艰巨的工作 因此,从最明显的问题开始:尽量将您的查询减少到绝对最小 例如 为什么在内部查询中选择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,以及SELECT的输出中的EmailCM—所以只选择这两列
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的索引吗
另一件事:所有外键列都应该被索引,以提高连接操作的速度,并帮助加快外键约束检查。您在这里使用的外键都被索引了吗
可能没有合适的索引来进行连接。您可以优化这两个子选择,但我怀疑查询优化器已经在这样做了
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
正如marc_指出的那样,优化不是一件快速的事情,也不是一个一招包换的解决方案。你最好的选择是阅读这个主题,看看一些入门技巧 您还应阅读解释计划工具或DB的等效变体,这是一个重要的优化工具;它将突出显示可能会减慢您在特定数据库上的查询速度的事情,例如全表扫描—消除这些扫描通常会给您带来快速的成功,并且通常会带来明显的改进 然而,我突然想到的两件事是: 您是否在用于加入的所有ID上设置了索引?否则,这将对性能产生负面影响 EmailStatus='Success'是一个字符串匹配,通常比较慢;如果没有看到你的解释计划的结果,很难说,但是你可能想考虑用一个数字状态代码代替一个状态表的外键,但是因为这可能是一个大的任务,如果解释计划强调它是一个问题,你应该只做它。
很好的注释,但是用必填字段替换“*”真的能提高那么多性能吗?SQL Server是否也在这样做,即优化子选择中的表读取?在子查询中选择*不是问题。SQL Server不会检索所有列,然后在以后丢弃它们,而是将子查询定义内联。e、 g.请参阅执行计划中的SELECT type FROM SELECT*FROM master..spt_值。T仅从NCI检索类型列。它不进行CI扫描。@marc_替换子选择中的*将不会产生任何影响。虽然您所说的对外部查询是正确的,但它对子选择或内部查询没有相同的影响,因为查询优化器实际上会将它们更改为外部查询中提到的字段,因此,这是一种自我优化的方法。也有可能您会返回多条记录,而您不希望它在每封电子邮件中返回超过1条记录,如果在多个表中发生这种情况,结果将变成指数级。例如,如果EmailID在tblCMEvalEmail表中不唯一,或者EmailSenderEmail在tblCMEvalEmail表中不唯一,那么这可能是加入的错误列?