SELECT w.OrderId,
w.OrderDate
FROM tblOrder AS w
INNER JOIN (
SELECT OrderID
FROM tblOrder
GROUP BY OrderID
HAVING MIN(CASE WHEN Status = 'DROP' THEN 1 ELSE 0 END) = 1
) AS d ON d.OrderID = w.OrderID
I immediately saw that this code run much faster. Then I started to think if the time spent optimizing the code was worth the time.
For testing I set up two identical SQL machines, one with SQL Server Enterprise 2005 SP2 and the other with SQL Server Enterprise 2000 SP4.
SQL Profiler was configured to measure CPU, DURATION, READS and WRITES.
These are the results I got with the old query on both boxes
|
SQL Server 2000
|
SQL Server 2005
|
|
DURATION
|
CPU
|
READS
|
WRITES
|
DURATION
|
CPU
|
READS
|
WRITES
|
|
1373
|
938
|
40236
|
25
|
546
|
516
|
22185
|
0
|
|
1310
|
922
|
40170
|
25
|
583
|
515
|
22433
|
0
|
|
1283
|
891
|
40170
|
25
|
548
|
485
|
22199
|
0
|
|
1360
|
953
|
40170
|
25
|
493
|
500
|
22210
|
0
|
|
1376
|
953
|
40170
|
25
|
494
|
500
|
22300
|
0
|
These are the results I got for the new query on both boxes
|
SQL Server 2000
|
SQL Server 2005
|
|
DURATION
|
CPU
|
READS
|
WRITES
|
DURATION
|
CPU
|
READS
|
WRITES
|
|
296
|
266
|
27322
|
25
|
185
|
156
|
18112
|
0
|
|
296
|
250
|
27272
|
25
|
164
|
172
|
18106
|
0
|
|
283
|
265
|
27272
|
25
|
167
|
172
|
18106
|
0
|
|
266
|
266
|
27272
|
25
|
169
|
172
|
18106
|
0
|
|
230
|
250
|
27272
|
25
|
168
|
156
|
18106
|
0
|
My first reaction was that the time spent optimizing the query was worth the time because the old query went from {1300, 900, 40000, 25} down to {300, 250, 27000, 25} on the SQL Server 2000 box, which is a speed improvement between 200% and 300%.
But the real surprise is that the old query without any optimization run almost as fast on the SQL Server 2005 box than the optimized query on SQL Server 2000 box.
My conclusion is that SQL Server 2005 has a better query engine and produces better execution plans than SQL Server 2000. This do not take away the fact that the optimized query is faster on both boxes.
The lesson learned here is that you can never throw in enough hardware to solve badly written code.
For completeness, I also post the execution plans for both queries
Old query
SQL Server 2000
|--Table Spool
|--Top
|--Nested Loops
|--Filter
| |--Compute Scalar
| |--Compute Scalar
| |--Hash Match
| |--Hash Match
| |--Clustered Index Scan
| |--Clustered Index Scan
|--Clustered Index Seek
SQL Server 2005
|--Compute Scalar
|--Sort
|--Top
|--Merge Join
|--Sort
| |--Filter
| |--Compute Scalar
| |--Hash Match
| |--Hash Match
| |--Clustered Index Scan
| |--Compute Scalar
| |--Clustered Index Scan
|--Clustered Index Scan
New query
SQL Server 2000
|--Table Spool
|--Top
|--Merge Join
|--Filter
| |--Stream Aggregate
| |--Clustered Index Scan
|--Clustered Index Scan
SQL Server 2005
|--Compute Scalar
|--Sort
|--Top
|--Merge Join
|--Filter
| |--Stream Aggregate
| |--Compute Scalar
| |--Clustered Index Scan
|--Clustered Index Scan
Continued here
http://weblogs.sqlteam.com/peterl/archive/2007/09/24/Finding-group-of-records-with-a-certain-status-II.aspx