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)
 Table variable to avoid LEFT JOIN

Author  Topic 

Lijo Cheeran Joseph
Posting Yak Master

123 Posts

Posted - 2010-02-16 : 10:40:25
Hi Team,

I am using SQL Server 2005. I have heared that LEFT OUTER JOIN is a significant performance reducing factor. Alternative is to use a table variable to avoid LEFT OUTER JOIN.

What I understand is that, we have to put all the values from the left table to the table variable, first. Then we have to UPDATE the table variable with the right table values. Then select from the table variable.

Has anyone come across this kind of approach? Could you please suggest a real time example (with query)? (E..g All the customers and their orders from Customer and Order tables).

Thanks
Lijo Cheeran Joseph

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2010-02-16 : 11:00:41
Nobody should state in general that LEFT OUTER JOIN is a significant performance reducing factor.
I have my doubts about table variable with lots of rows and good performance.

Ways to increase the speed of a query always depends on even that query.
Performance tuning is more a kind of art than a matter of general rules.


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-16 : 11:07:12
"All the customers and their orders from Customer and Order tables)"

Do you really want ALL customers and ALL orders?

Presumably that is a lot of data (or it will be in the future)

Unless you are exporting to another system then it is more likely that you want "The first 100 customers ..." then "The next 100 customers"

LEFT OUTER JOIN causing performance issues is rubbish. Badly written queries cause performance issues.

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

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2010-02-16 : 11:10:15
I think you should post your query.

This doesn't sound like a situation where you'd want to use any kind of temporary storage. Especially if you are dealing with a large set of date.

This
quote:

What I understand is that, we have to put all the values from the left table to the table variable, first. Then we have to UPDATE the table variable with the right table values. Then select from the table variable.

Doesn't make any sense to me.

As long as you have decent relationships (index) between the two tables involved the left join isn't going to be an issue.

If you only care if *any* row exists in the right table for a given row in the left table then using EXISTS is certainly faster but for what I think you want a LEFT JOIN would be the best approach.

Post a details scenario though if you want to discuss.


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

Lijo Cheeran Joseph
Posting Yak Master

123 Posts

Posted - 2010-02-16 : 11:37:58
Hi Team,

Thanks for your replies.

1) I have not written a query for this. My question is - if someone has used a similar approach, I would like to know the scenario and how they handled it.

2) Please assume that number of records in the Order and Customer tables is less than 100. (May be a custom made luxury car company will have such a table, right). :-)

3) I am looking for all the customers and all the orders


If we had got an answer, we could have made a comparison of performance (and actually see the result).


Thanks
Lijo Cheeran Joseph
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2010-02-16 : 11:45:23
less than 100 records?
You can do what you want - it is always fast.


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-16 : 12:27:31
100 records.

You'll be lucky to see any difference with any method.

Try something like this -- put this in a scrub database and have a play around. Lots of random data

-- Base Tables
IF OBJECT_ID('orders') IS NOT NULL DROP TABLE orders
IF OBJECT_ID('customers') IS NOT NULL DROP TABLE customers

CREATE TABLE customers (
[customerID] INT IDENTITY(1,1)
, [firstname] VARCHAR(255)
, [surname] VARCHAR(255)

PRIMARY KEY NONCLUSTERED ([customerID])
)

CREATE TABLE orders (
[orderID] INT IDENTITY(1,1)
, [customerID] INT FOREIGN KEY REFERENCES dbo.customers ([customerID])
, [orderDate] DATETIME
, [orderAmount] MONEY

PRIMARY KEY NONCLUSTERED ([orderId])
)

CREATE CLUSTERED INDEX IX_customers_surname_firstname ON customers ([surname], [firstname])
CREATE CLUSTERED INDEX IX_orders_date_amount_customerID ON orders ([orderDate], [orderAmount], [customerID])

-- Data (262144 Customer Rows)
INSERT customers ([firstname], [surname])
SELECT
LEFT(CAST(NEWID() AS VARCHAR(50)), 8)
, LEFT(CAST(NEWID() AS VARCHAR(50)), 8)
FROM
( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS a
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS b
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS c
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS d
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS e
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS f
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS g
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS h
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS i

-- 1048576 Order Rows
INSERT orders ([customerID], [orderDate], [orderAmount])
SELECT
ABS(CAST(CAST(NEWID() AS VARBINARY(2)) AS INT)) + 1 -- There will be a customer in this range
, CAST(ABS(CAST(CAST(NEWID() AS VARBINARY(2)) AS INT)) AS DATETIME) -- valid date in this range
, CAST(CAST(NEWID() AS VARBINARY(3)) AS MONEY) -- valid money in this range
FROM
( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS a
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS b
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS c
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS d
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS e
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS f
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS g
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS h
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS i
CROSS JOIN ( SELECT 1 AS [a] UNION SELECT 2 AS [2] UNION SELECT 3 AS [3] UNION SELECT 4 AS [4]) AS j


-- Everything (Non Clustered Index scan galore!)
SELECT
*
FROM
customers c
LEFT JOIN orders o ON o.[customerID] = c.[customerID]

-- Employees surname greater than C (Clustered index seek on customers -- scan on the orders table)
SELECT
*
FROM
customers c
LEFT JOIN orders o ON o.[customerID] = c.[customerID]
WHERE
c.[surname] > 'C'


-- Employees surname greater than C wand order dates after 2010
-- Index seeks on both
SELECT
*
FROM
customers c
LEFT JOIN orders o ON
o.[customerID] = c.[customerID]
AND o.[orderDate] >= '20100101'
WHERE
c.[surname] > 'C'


Index(s) may not be the best but they'll give you an idea of selectivity.

If you are actually wanting to select EVERYTING then you'll always get (at best) a clustered index scan on both tables -- I think Kristen mentioned something earlier.

Play around with that. My guess is if you implement your table variable idea you'll be waiting a LONG LONG time before you get a result.




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

- Advertisement -