| Author |
Topic |
|
kumar1248
Starting Member
20 Posts |
Posted - 2009-06-10 : 00:51:13
|
Hi team,I have a query that has around 100 JOIN conditions. I am observing as soon as i add a new JOIN to my query,the performance is getting down. Taking longer and longer times to execute the query.In my JOIN statements there are couple conditions like SELECT A.ValQuote,B.Description,C.NetID,D.ProcDesc FROM dbo.TableA A JOIN dbo.TableB B JOIN dbo.TableC C ON C.NetID = B.NetID AND C.Description = 'RULE3' JOIN dbo.TableD D ON D.SrlNo = C.SrlNo AND D.ProcType = 'TYPE3' ON B.BusnID = A.BusnID AND B.SlotLoad = 'Full' My questions are:1) The above type of coditions writing is better or same JOIN like below performs better ? SELECT A.ValQuote,B.Description,C.NetID,D.ProcDesc FROM dbo.TableA A JOIN dbo.TableB B JOIN dbo.TableC C ON C.NetID = B.NetID JOIN dbo.TableD D ON D.SrlNo = C.SrlNo ON B.BusnID = A.BusnIDWHERE C.Description = 'RULE3' AND D.ProcType = 'TYPE3' AND B.SlotLoad = 'Full' In otherwords, mentioning the condtion combining with JOIN condition with AND clause is better or after all JOIN condtions mentioning with WHERE clause ?2) How to do performance tune a query with morethan 100 JOIN conditions?Please advice.THanks,Kumar |
|
|
Lumbago
Norsk Yak Master
3271 Posts |
Posted - 2009-06-10 : 02:54:06
|
| As far as I know the performance is exactly the same as long as you're using an INNER JOIN like you are here. However, when using LEFT/RIGHT OUTER JOIN the logic is different and you might get different results depending on where you place your filtering criteria. Hence it can produce a different query plan and perform differently. It is however considered good coding practice to keep the filtering conditions in the WHERE statement and the JOIN conditions in the JOIN statements. This is mostly for readability purposes.- Lumbago |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-06-10 : 03:29:51
|
In most cases, SQL Server is smart enough to know how and when to filter, ie the two approaches are the same.But this is not always true. I tend to put the filtering at the ON part just for sure. E 12°55'05.63"N 56°04'39.26" |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-06-10 : 03:35:05
|
Another approach is to only fetch the columns that are interesting and needed, like this.This approach can have a huge impact on performanceSELECT a.ValQuote, b.[Description], c.NetID, d.ProcDescFROM ( SELECT DISTINCT BusnID, ValQuote FROM dbo.TableA ) AS aINNER JOIN ( SELECT DISTINCT BusnID, [Description], NetID FROM dbo.TableB WHERE SlotLoad = 'Full' ) AS b ON b.BusnID = a.BusnIDINNER JOIN ( SELECT DISTINCT NetID, SrlNo FROM dbo.TableC WHERE [Description] = 'RULE3' ) AS c ON c.NetID = b.NetID INNER JOIN ( SELECT DISTINCT SrlNo, ProcDesc FROM dbo.TableD WHERE ProcType = 'TYPE3' ) AS d ON d.SrlNo = c.SrlNo The DISTINCT keyword may not be necessary due to your business rules. E 12°55'05.63"N 56°04'39.26" |
 |
|
|
kumar1248
Starting Member
20 Posts |
Posted - 2009-06-10 : 13:47:31
|
| Thanks Lumbago and Peso.Peso, the approach that you are describing, I am not sure how this works out in point of performance, But i havent seen this type of apporach for getting the data. Is this apporach is a Valid approach ? I mean , Is it advaced way doing the things or .. ? Please explain. Why i am asking is in my company we need to write code as per coding standards and we need to follow JOINS as they should. The query you wrote is seems to be SUB QUERYs , please correct me if i am misunderstanding.Hi SQLTeam , Please suggest any other ways of handling Lot of JOINS in querys. How to gain performance on this? One of my friend is telling we can divide the query in to multiple queries , 10-15 joins in each query , and then join the results together. One more thing here is i am joing the VIEWS , and not the actual tables.Thanks,kumar |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-06-10 : 14:43:30
|
No, it's not subquery. They are derived tables.The reason this may be faster is that SQL Server need less records to build HASH values for when using INNER HASH JOIN for joining tables with 1000 or more records. E 12°55'05.63"N 56°04'39.26" |
 |
|
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2009-06-10 : 18:22:02
|
quote: Originally posted by Peso In most cases, SQL Server is smart enough to know how and when to filter, ie the two approaches are the same.But this is not always true. I tend to put the filtering at the ON part just for sure.
I agree with Peso that in most cases SQL is smart enough to figure it out and each approach should work equally well. As for where to put the filtering, I again, agree with Peso. The reason for moving the filtering out of the WHERE clause an up into the JOIN is mostly preference because, as stated, 2005 and above is pretty smart. However, I believe that putting trying to restrict data as soon as possible is best. Although, this is probably a hangover from 7.0 and 2000 where the query optimizer wasn't always smart enough to figure that out and there was performance to gain by doing such things. |
 |
|
|
Lumbago
Norsk Yak Master
3271 Posts |
Posted - 2009-06-11 : 03:10:57
|
| Have you actually seen performance differences when filtering in the where-clause instead of the joins in sql server 2005? Sub-queries and derived tables are of course a completely different story but for plain inner joins like in the example?- Lumbago |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-06-11 : 04:21:05
|
Oh yes. It depends very much on the index strategy.Even with covering indexes, the four approaches produces the same plan but behaves very different in CPU and DURATION.The difference in time can be as much as 5 times as slow!For the code below, please try out other index strategies, such as* CREATE NONCLUSTERED INDEX IX_Left ON #Left (j, i)* CREATE NONCLUSTERED INDEX IX_Left ON #Left (i) INCLUDE (j)* CREATE NONCLUSTERED INDEX IX_Left ON #Left (j) INCLUDE (i)* Of course the same goes for the #Right table.* There will be 16 combinations for you to test. 4 strategies for each table. Remember all these are covering indexes!USE [Master]GODROP TABLE #Left, #RightCREATE TABLE #Left ( i INT NOT NULL, j INT NOT NULL )INSERT #LeftSELECT ABS(CHECKSUM(NEWID())) % 20000, ABS(CHECKSUM(NEWID())) % 200FROM sysobjects AS so1CROSS JOIN sysobjects AS so2-- 3 966 001 records affectedCREATE NONCLUSTERED INDEX IX_Left ON #Left (i, j)CREATE TABLE #Right ( i INT NOT NULL, j INT NOT NULL )INSERT #RightSELECT ABS(CHECKSUM(NEWID())) % 20000, ABS(CHECKSUM(NEWID())) % 200FROM sysobjects AS so1CROSS JOIN sysobjects AS so2-- 3 966 001 records affectedCREATE NONCLUSTERED INDEX IX_Right ON #Right (i, j)-- Peso 1SELECT l.i, r.iFROM #Left AS lINNER JOIN #Right AS r ON r.i = l.iWHERE l.j = 12 AND r.j = 21-- 20 169 records affected-- Peso 2SELECT l.i, r.iFROM #Left AS lINNER JOIN #Right AS r ON r.i = l.i AND r.j = 21WHERE l.j = 12-- 20 169 records affected-- Peso 3SELECT l.i, r.iFROM ( SELECT i FROM #Left WHERE j = 12 ) AS lINNER JOIN #Right AS r ON r.i = l.i AND r.j = 21-- 20 169 records affected-- Peso 4SELECT l.i, r.iFROM ( SELECT i FROM #Left WHERE j = 12 ) AS lINNER JOIN ( SELECT i FROM #Right WHERE j = 21 ) AS r ON r.i = l.i-- 20 169 records affected E 12°55'05.63"N 56°04'39.26" |
 |
|
|
kumar1248
Starting Member
20 Posts |
Posted - 2009-06-11 : 22:59:08
|
| Thanks to all.I am working on these and let you know for any help. |
 |
|
|
kumar1248
Starting Member
20 Posts |
Posted - 2009-06-15 : 19:23:02
|
| Hi Team,As i told you before that my query contains 100 JOIN conditons appx. My organization is suggesting me to Split the joins in to 15-20 Max JOINS in each query and then combine the results to get the final output.I am in confusion how to do this. I know onething clearly , there is EMPLOYEE (Master) table in which i am JOINing with all the other child tables . For each 15- 20 JOINS set , i should use this EMPLOYEE table. What is the good way of implementing this? Please suggest. |
 |
|
|
Lumbago
Norsk Yak Master
3271 Posts |
Posted - 2009-06-16 : 03:19:01
|
| I'd say this is a database design problem and not a query performance problem. Do you add new tables to your database dynamically or something? If you constantly need to add more joins to your query you should consider redesigning the table structures to be more dynamic.- Lumbago |
 |
|
|
|