Wednesday, September 29, 2010

Sql Server query Optimization

Optimization in Practice

Example 1:
I want to retrieve the name and salary of the employees of the R&D department.


Original:
Query : Select * From Employees
In Program : Add a filter on Dept or use command : if Dept = R&D--

Corrected :
Select Name, Salary From Employees Where Dept = R&D--

In the corrected version, the DB filters data because it filters faster than the program.
Also, you only need the Name and Salary, so only ask for that.
The data that travels on the network will be much smaller, and therefore your performances will improve.

Example 2 (Sorting):

Original:
Select Name, Salary
From Employees
Where Dept = 'R&D'
Order By Salary

Do you need that Order By Clause? Often, people use Order By in development to make sure returned data are ok; remove it if you don't need it.
If you need to sort the data, do it in the query, not in the program.

Example 3:
Original:
For i = 1 to 2000
Call Query : Select salary From Employees Where EmpID = Parameter(i)

Corrected:
Select salary From Employees Where EmpID >= 1 and EmpID <= 2000

The original Query involves a lot of network bandwidth and will make your whole system slow.
You should do as much as possible in the Query or Stored Procedure. Going back and forth is plain stupid.
Although this example seems simple, there are more complex examples on that theme.
Sometimes, the processing is so great that you think it's better to do it in the code but it's probably not.
Sometimes, your Stored Procedure will be better off creating a temporary table, inserting data in it and returning it than going back and forth 10,000 times.
You might have a slower query that saves time on a greater number of records or that saves bandwidth.

Example 4 (Weak Joins):
You have two tables Orders and Customers. Customers can have many orders.

Original:
Select O.ItemPrice, C.Name
From Orders O, Customers C

Corrected:
Select O.ItemPrice, C.Name
From Orders O, Customers C
Where O.CustomerID = C.CustomerID

In that case, the join was not there at all or was not there on all keys. That would return so many records that your query might take hours.
It's a common mistake for beginners.

Corrected 2:
Depending on the DB you use, you will need to specify the Join type you want in different ways.
In SQL Server, the query would need to be corrected to:

Select O.ItemPrice, C.Name
From Orders O INNER JOIN Customers C ON O.CustomerID = C.CustomerID

Choose the good join type (INNER, OUTER, LEFT, ...).
Note that in SQL Server, Microsoft suggests you use the joins like in the Corrected 2 instead of the joins in the Where Clause because it will be more optimized.

Example 5 (Weak Filters):
This is a more complicated example, but it illustrates filtering at its best.
We have two tables -- Products (ProductID, DescID, Price) and Description(DescID, LanguageID, Text). There are 100,000 Products and unfortunately we need them all.
There are 100 languages (LangID = 1 = English). We only want the English descriptions for the products.

We are expecting 100 000 Products (ProductName, Price).

First try:
Select D.Text As ProductName, P.Price
From Products P INNER JOIN Description D On P.DescID = D.DescID
Where D.LangID = 1

That works but it will be really slow because your DB needs to match 100,000 records with 10,000,000 records and then filter that Where LangID = 1.
The solution is to filter On LangID = 1 before joining the tables.

Corrected:
Select D.Text As ProductName, P.Price
From (Select DescID, Text From Description Where D.LangID = 1) D
INNER JOIN Products P On D.DescID = P.DescID

Now, that will be much faster. You should also make that query a Stored Procedure to make it faster.

Example 6 (Views):
Create View v_Employees AS
Select * From Employees

Select * From v_Employees

This is just like running Select * From Employees twice.
You should not use the view in that case.

If you were to always use the data for employees of R&D and would not like to give the rights to everyone on that table because of salaries being confidential,
you could use a view like that:

Create View v_R&DEmployees AS
Select Name, Salary From Employees Where Dept = 1
(Dept 1 is R&D).

You would then give the rights to View v_R&DEmployees to some people and would restrict the rights to Employees table to the DBA only.

That would be a possibly good use of views.

0 comments:

Post a Comment