| 
	
 | 
 Posted by serge on 12/06/05 07:34 
How do I determine which method I should use if 
I want to optimize the performance of a database. 
 
I took Northwind's database to run my example. 
 
My query is I want to retrieve the Employees' First 
and Last Names that sold between $100,000 and 
$200,000. 
 
First let me create a function that takes the EmployeeID 
as the input parameter and returns the Employee's 
First and Last name: 
 
CREATE FUNCTION dbo.GetEmployeeName( 
    @EmployeeID INT 
) 
RETURNS VARCHAR(100) 
AS 
BEGIN 
 
DECLARE @NAME VARCHAR(100) 
 
SELECT @NAME = FirstName + ' ' + LastName 
FROM Employees 
WHERE EmployeeID = @EmployeeID 
 
RETURN ISNULL(@NAME, '') 
 
END 
 
 
My first method to run this: 
 
SELECT EmployeeID, dbo.GetEmployeeName(EmployeeID) AS 
    Employee, SUM(UnitPrice * Quantity) AS Amount 
FROM Orders 
        JOIN [Order Details] ON Orders.OrderID = 
    [Order Details].OrderID 
GROUP BY EmployeeID, 
    dbo.GetEmployeeName(EmployeeID) 
HAVING SUM(UnitPrice * Quantity) BETWEEN 
    100000 AND 200000 
 
It's running in 4 seconds time. And here are the 
Statistics IO and Time results: 
 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
SQL Server parse and compile time: 
   CPU time = 17 ms, elapsed time = 17 ms. 
 
(3 row(s) affected) 
 
Table 'Order Details'. Scan count 1, logical reads 10, 
    physical reads 0, read-ahead reads 0. 
Table 'Orders'. Scan count 1, logical reads 21, 
    physical reads 0, read-ahead reads 0. 
 
SQL Server Execution Times: 
   CPU time = 3844 ms,  elapsed time = 3934 ms. 
 
SQL Server Execution Times: 
   CPU time = 3844 ms,  elapsed time = 3935 ms. 
 
SQL Server Execution Times: 
   CPU time = 3844 ms,  elapsed time = 3935 ms. 
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms. 
 
 
 
 
Now my 2nd method: 
 
IF (SELECT OBJECT_ID('tempdb..#temp_Orders')) IS NOT NULL 
        DROP TABLE #temp_Orders 
GO 
 
SELECT EmployeeID, SUM(UnitPrice * Quantity) AS Amount 
INTO #temp_Orders 
FROM Orders 
        JOIN [Order Details] ON Orders.OrderID = 
    [Order Details].OrderID 
GROUP BY EmployeeID 
HAVING SUM(UnitPrice * Quantity) BETWEEN 
    100000 AND 200000 
GO 
 
SELECT EmployeeID, dbo.GetEmployeeName(EmployeeID), 
Amount 
FROM #temp_Orders 
GO 
 
It's running in 0 seconds time. And here are the Statistics IO 
and Time results: 
 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 0 ms. 
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms. 
Table '#temp_Orders0000000000F1'. Scan count 0, logical 
    reads 1, physical reads 0, read-ahead reads 0. 
Table 'Order Details'. Scan count 830, logical reads 1672, 
    physical reads 0, read-ahead reads 0. 
Table 'Orders'. Scan count 1, logical reads 3, physical reads 0, 
    read-ahead reads 0. 
 
QL Server Execution Times: 
   CPU time = 15 ms,  elapsed time = 19 ms. 
 
(3 row(s) affected) 
 
 
SQL Server Execution Times: 
   CPU time = 15 ms,  elapsed time = 19 ms. 
 
SQL Server Execution Times: 
   CPU time = 15 ms,  elapsed time = 20 ms. 
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 1 ms. 
 
(3 row(s) affected) 
 
Table '#temp_Orders0000000000F1'. Scan count 1, 
    logical reads 2, physical reads 0, read-ahead reads 0. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 3 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 3 ms. 
 
SQL Server Execution Times: 
   CPU time = 0 ms,  elapsed time = 3 ms. 
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms. 
 
 
By the way why "SQL Server Execution Times" 
exists 3 times and not just one time? 
 
 
Summary: 
 
The first code is clean, 1 single SELECT statement but 
takes 4 long seconds to execute. The logical reads are 
very few compared to the second method. 
 
 
The second code is less clean and uses a temp table but 
takes 0 second to execute. The logical reads are way 
too high compared to the first method. 
 
 
What am I supposed to conclude in this example? 
Which method should I use over the other and why? 
Are both methods good depending on which I prefer? 
If I can wait four seconds, it's better to reduce the logical 
reads in order to provide less Blocking on the live tables 
in a heavily accessed database? 
 
Which method should I choose on my own database? 
Calling a function like dbo.GetEmployeeName gets 
processed per each returned row, correct? That means 
If i had a scenario where 1000 records were to be returned 
would it be better to dump 1000 records to a temp table 
variable and then call a function to process each record 
one at a time? 
 
Or would the direct approach without using 
a temp table cause slower processing and more 
blocking/deadlocks because I am calling the function 
per each row as I am accessing directly from the tables? 
 
Thank you
 
  
Navigation:
[Reply to this message] 
 |