March 6, 2006 at 2:54 pm
I have a question concerning a SQL query. I have a query whose inner query returns a very small number of records, say under 500. Then, in the outer query I join it with a number of tables. This query takes a very long time to execute (like 40 seconds or more). When I execute the inner query, it only takes a couple seconds to execute. The joins in the outer, in theory, shouldn’t take too long since they act only on a limited number of records. But, they seem to be making a very large difference. When testing the query, each join I include in the outer query increases the execution time by several seconds. So it appears to me the query optimizer isn’t doing the inner query first, then joining those limited number of rows in the outer. Any ideas on how I can fix this?
TSQL below
SELECT *
FROM (
SELECT
QP1.CreditUnionID,
QP1.QuoteNumber,
QU1.QuoteID,
QU1.QuotePackageID,
QU1.QuotingBranchID,
QU1.ProductID,
QU1.QuotingUserID,
QU1.DateQuoted,
QU1.DateExpires,
QU1.TotalTaxes,
QU1.TotalPremium,
QU1.TotalBuyerDiscount,
QU1.TotalBuyerCost,
QU1.TotalCUCompensation,
QU1.TotalASCompensation,
QU1.TotalUWCompensation,
QU1.TotalVICompensation,
QU1.TotalDueAllied,
QU1.QuoterIncentive,
QU1.IssuerIncentive,
QU1.TotalCreditGivenByAS,
QU1.TotalCreditGivenByCU,
QU1.TotalBuyerCredit
FROM Quotes QU1
JOIN Applications AP1 ON AP1.QuoteID = QU1.QuoteID
JOIN QuotePackages QP1 ON QP1.QuotePackageID = QU1.QuotePackageID
JOIN ObjectStatus AS1 ON AS1.ObjectID = QU1.QuoteID AND AS1.EventCategoryID = 1
JOIN ObjectStatus PS1 ON PS1.ObjectID = QU1.QuoteID AND PS1.EventCategoryID = 2
WHERE QU1.IsRemoved = 0 AND QP1.CreditUnionID = 292 AND QU1.ProductID = 2 AND AS1.EventID IN (2,1,5) AND PS1.EventID IN (0,12)) FD
INNER JOIN JOIN Applications AP2 ON AP2.QuoteID = FD.QuoteID
INNER JOIN JOIN CreditUnions CU2 ON CU2.CreditUnionID = FD.CreditUnionID
INNER JOIN JOIN QuoteMemberInfo MI2 ON MI2.QuotePackageID = FD.QuotePackageID
INNER JOIN JOIN Users US1 ON US1.UserID = FD.QuotingUserID
INNER JOIN JOIN Users US2 ON US2.UserID = AP2.IssuingUserID
INNER JOIN JOIN Products PR2 ON PR2.ProductID = FD.ProductID
INNER JOIN ObjectStatus AS2 ON AS2.ObjectID = FD.QuoteID AND AS2.EventCategoryID = 1
INNER JOIN Events AE2 ON AE2.EventID = AS2.EventID
INNER JOIN ObjectStatus MS2 ON MS2.ObjectID = FD.QuotePackageID AND MS2.EventCategoryID = 8
INNER JOIN Events ME2 ON ME2.EventID = MS2.EventID
INNER JOIN ObjectStatus VS2 ON VS2.ObjectID = FD.QuoteID AND VS2.EventCategoryID = 21
INNER JOIN Events VE2 ON VE2.EventID = VS2.EventID
March 6, 2006 at 3:02 pm
Do you need all columns from all thirteen tables returned. This could be potentialy an enormous amount of data if VarChar(8000), text, ntext and images are present.
I would start by limiting the columns returned to what is needed then we can go through the query plan!
March 6, 2006 at 6:38 pm
Yep, I agree with Kory...
Also, I believe that moving the reference to constants out of the ON clauses and into a WHERE clause will help a bit...
The other thing may be that you may have some joins that return more than 1 row for a given condtion which will cause many more rows than what you're looking for to be returned... not quite as bad as a CrossJoin but almost.
--Jeff Moden
Change is inevitable... Change for the better is not.
March 6, 2006 at 6:44 pm
What about indexes on joined fields?
Look on Execution Plan for this query.
_____________
Code for TallyGenerator
March 6, 2006 at 8:17 pm
Ok, set statistic IO on and showplan and post the output. After that you can specify the columns needed and then re-run the SQL with statistic IO on and we can see how many less pages are read.
March 6, 2006 at 10:48 pm
I'm working on pairing down the number of columns returned. Good call... there was a ridiculous number of them.
I was thinking the same thing regarding the indexes... I took a peak at the execution plan... no table scans.
I was hoping to throw an index or two down and be done with it.
I'm not used to performance tweaking queries of such magnitude, so I appreciate the comments that you all do have.
Here is the statistic IO info:
Table 'Applications'. Scan count 2, logical reads 3422, physical reads 1, read-ahead reads 3251.
Table 'ObjectStatus'. Scan count 8, logical reads 5899, physical reads 1, read-ahead reads 5011.
Table 'Quotes'. Scan count 1, logical reads 11150, physical reads 32, read-ahead reads 10714.
Table 'QuoteMemberInfo'. Scan count 1, logical reads 11043, physical reads 29, read-ahead reads 11007.
Table 'QuotePackages'. Scan count 1, logical reads 12, physical reads 0, read-ahead reads 10.
Table 'Users'. Scan count 2, logical reads 619, physical reads 0, read-ahead reads 0.
Table 'Events'. Scan count 3, logical reads 12, physical reads 0, read-ahead reads 0.
Table 'CreditUnions'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.
Table 'Products'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0.
The SHOWPLAN_ALL is pretty nasty... ar Is there a certain few columns that would help? I've been trying to get the result set put in there and it's just a monster...
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply