Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Optimizing query

Author  Topic 

Lijo Cheeran Joseph
Posting Yak Master

123 Posts

Posted - 2010-02-17 : 09:00:30
Hi Team,

Following query explains two approaches. Both of them took 19 seconds.

Could you please list any scenario where the second approach will be faster than the first. (E.g. More number of record in first table or second table; Using other indexes; etc).

What are the ways to optimize the second approach?



CREATE TABLE #MainTable (
CustomerID INT PRIMARY KEY,
FirstName VARCHAR(100)
)


DECLARE @Count INT
SET @Count = 0

DECLARE @Iterator INT
SET @Iterator = 0

WHILE @Count <8000
BEGIN

INSERT INTO #MainTable SELECT @Count, 'Cust'+CONVERT(VARCHAR(10),@Count)
SET @Count = @Count+1

END

CREATE TABLE #RightTable
(
OrderID INT PRIMARY KEY,
CustomerID INT,
Product VARCHAR(100)
)

CREATE INDEX [IDX_CustomerID] ON #RightTable (CustomerID)

WHILE @Iterator <400000
BEGIN

IF @Iterator % 2 = 0
BEGIN

INSERT INTO #RightTable SELECT @Iterator,2, 'Prod'+CONVERT(VARCHAR(10),@Iterator)
END
ELSE
BEGIN
INSERT INTO #RightTable SELECT @Iterator,1, 'Prod'+CONVERT(VARCHAR(10),@Iterator)
END

SET @Iterator = @Iterator+1

END


-- Approach 1: Using LEFT JOIN
SELECT mt.CustomerID,mt.FirstName,COUNT(rt.Product) [CountResult]
FROM #MainTable mt
LEFT JOIN #RightTable rt ON mt.CustomerID = rt.CustomerID
GROUP BY mt.CustomerID,mt.FirstName


---------------------------



-- Approach 2: Using Table variable Update
DECLARE @WorkingTableVariable TABLE
(
CustomerID INT,
FirstName VARCHAR(100),
ProductCount INT
)

INSERT INTO @WorkingTableVariable (CustomerID,FirstName)
SELECT CustomerID, FirstName FROM #MainTable

UPDATE @WorkingTableVariable
SET ProductCount = [Count]
FROM @WorkingTableVariable wt
INNER JOIN
(SELECT CustomerID,COUNT(rt.Product) AS [Count]
FROM #RightTable rt
GROUP BY CustomerID) IV ON wt.CustomerID = IV.CustomerID

SELECT CustomerID,FirstName, ISNULL(ProductCount,0) [CountResult] FROM @WorkingTableVariable
ORDER BY CustomerID

--------

DROP TABLE #MainTable
DROP TABLE #RightTable




I hope, by some tuning the second approach will give better performance than the LEFT JOIN.

Is there any different example that has the second approach working faster?

Thanks
Lijo Cheeran Joseph

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2010-02-17 : 09:20:37
Both approaches are running less than 1 second on my testmachine.
I don't see any reason for tuning.

But honestly I thought that the second approach would take a lot more time than the first. I'm a bit surprised


No, you're never too old to Yak'n'Roll if you're too young to die.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-17 : 09:33:15
is this different to your earlier question:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=139944

I don't understand why you think you need to work around a LEFT JOIN by using a TEMP table

My answer remains the same:

"if you have a query that is performing badly post the Query Plan here and I am sure folk here will give you advice on how to improve it."
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-17 : 09:53:05
"But honestly I thought that the second approach would take a lot more time than the first"

Mostly the time to display 8,000 rows on your screen?

The index [IDX_CustomerID] is unused - the data is not selective - whereas I expect the real word data would be.
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2010-02-17 : 15:50:27
What I meaned was:
The first approach should be faster because there is only the select-query with join. Nothing more

The second approach has a lot more to do:
- declare a table
- insert into table
- update that table (with join too)
- do the select to show the result


No, you're never too old to Yak'n'Roll if you're too young to die.
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-18 : 03:11:06
" What I meaned was"

Yup I assumed that, but given that it selects 8,000 rows I think most of the time is to display them - if you are just timing how long the query takes start-to-finish.

Inserting the results into a temporary table (so no display to screen) might make a more comparable test.

But maybe they both take the same amount of time because, in effect, SQL is doing that anyway (internally) for the first query.

But I don't see any useful purpose to replacing Left Joins with temporary tables ...
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2010-02-18 : 03:35:56
But I don't see any useful purpose to replacing Left Joins with temporary tables ...
I agree


No, you're never too old to Yak'n'Roll if you're too young to die.
Go to Top of Page

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2010-02-18 : 04:30:59
Agreed to all comments. Version 2 is unnecessary. Kristen's point about the index is good. Also why does this post exist? It is exactly the same question as http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=139944 where we tried to help you earlier?

Just to add one more thing to the pile:

Approach 2 will probably end up creating a temp table (hidden from you) rather than a table variable to hold the data (if there is enough data)

If we assume that you would actually be querying base tables rather than the two temp tables in your example then this will cause the query plan to be recompiled every time which isn't good.

We had a similar thing in production a while ago where there was a very small query that never managed to reuse a query plan. Factoring out the temporary storage and using different JOINS (and a CTE) meant the query could reuse the same plan. As the compilation time was actually greater than the run time of the query then we immediately saw over a 100% jump in performance. (the changes also made things better from a code point of view).


Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-02-18 : 05:57:24
" then this will cause the query plan to be recompiled every time"

Good point.
Go to Top of Page
   

- Advertisement -