Reputation: 926
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. What's problem with my query that it takes so much time?
Upvotes: 0
Views: 3629
Reputation: 526
As marc_s points out, optimization is not a quick thing to do, nor is it a one-trick-fixes-all solution. Your best bet is to read up on the topic (see http://beginner-sql-tutorial.com/sql-query-tuning.htm for some starter tips).
You should also read up on the EXPLAIN PLAN tool (or equivalent variation for your DB) which is a vital optimisation tool; 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:
Upvotes: 0
Reputation: 21487
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
Upvotes: 0
Reputation: 754230
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.
E.g.
SELECT *
in your inner queries, when you're only ever using a single (or two) columns from that data? 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!
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!
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, e.g. that will return exactly those columns you need. So do you have an index on dbo.tblCMEvalEmail
with the EmailSenderEMail
column? Do you have an index on dbo.tblCMEvalEmailInfo
that contains the two columns 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. Are you foreign keys used here all indexed?
Upvotes: 2