If you've worked with SQL Server databases for any amount of time, it's practically a given that you've run into slow running queries. Sometimes the reason for the slow response time is due to the load on the system, and other times it is because the query is not written to perform as efficiently as possible (I find this reason much more common). Learn how you may be able to improve performance by knowing what to look for in your query designs.

Operate on small sets

The fewer rows you are dealing with, the quicker you will find what you want. If the query optimiser sees that the number of rows in the table is sufficiently small, no indexes on that table will be used. The optimiser will realise that it is faster to scan the rows in the table to satisfy the request rather than traverse an index structure to find the rows.

Limit the columns returned

When returning data in your applications, the less data that is returned, the faster the information is transmitted over the network -- this goes for the amount of rows returned, as well as the number of columns returned. This is why I am against using the SELECT * statement, especially in a production environment. In my experience with database administration and development, I have seen very few times that have warranted using a SELECT * statement. The reason for this is twofold. It doesn't make sense to bring back columns that you are not going to be using. The second reason (which I feel is more important) is that using SELECT * can break existing code. Consider the following example.

I have an INSERT statement in my production environment. I use a SELECT * statement as a data source in my INSERT statement. This isn't a big deal because my SourceTable has the same number of columns in it as the DestinationTable.

SELECT INTO DestinationTable
(Fld1, Fld2, Fld3)
SELECT *
FROM SourceTable.

A business situation arises in which I need to add a field to my SourceTable table.

ALTER TABLE SourceTable
ADD Fld4 INT

Adding this new field will break my INSERT statement, which will cause problems in my production environment.

Searching for rows

The manner in which rows are searched for in a database table will always be one of the more vital implementations in your database environment. The SQL Server query optimiser will operate much more efficiently for some WHERE statements as compared to other WHERE statements based upon how the statement is written even if the outcome of the statements is the same.

The following example uses the IN() statement to specify a series of values being searched for. For this example, assume the OrderID column as a NonClustered index.

SELECT * FROM ProductSales
WHERE OrderID IN(4494, 4495, 4496)

This statement is exaactly the same as using an OR operator to specify the three values being searched for. Either statement will cause SQL Server not to use the index on the field and to cycle through the rows in the table searching for the values. Since the values used in the example are contiguous, I can use the BETWEEN operator instead. This will allow the query optimiser to effectively use the index.

SELECT * FROM ProductSales
WHERE OrderID BETWEEN 4494 AND 4496

In general, most types of exclusion statements in your WHERE clause will cause SQL Server to not be able to use an index. The following are some additional examples:

<>, !, OR, NOT IN, NOT EXISTS


The manner in which LIKE statements are used also makes a difference. If you are able to specify the beginning character(s) of the statement you are searching for, you will have a better chance of your statement using an index. If you specify a wildcard(%) before any type of search string, the optimiser will be unable to use an index.


SELECT * FROM Customers WHERE LastName LIKE '%TR%'

Date searches

Date searches are sometimes a little tricky to perform in the database; for instance, I have seen numerous situations where date functions are used for date searches. In the following example, the sales records are being retrieved from the SalesHistorry table for August 15, 2005:

SELECT SaleID
FROM SalesHistory
WHERE
MONTH(SaleDate) = 8 AND
YEAR(SaleDate) = 2005 AND
DAY(SaleDate) = 15

The functions in the WHERE clause will cause SQL Server to perform the function on every row being searched, which means the index will not be used. This is why I discourage the returns values from functions to be used as criteria in queries. The following code shows how you can rewrite the statement so that an index is used, and the results are returned in a much quicker fashion.

SELECT SaleID
FROM SalesHistory
WHERE
SaleDate >= '8/15/2005' AND
SaleDate < '8/16/2005'

Next time

In my next column, I plan to look at some of the more advanced techniques that you can use to optimise queries.

Database Jumping This was published in Database Jumping, check every Thursday for more stories

Comments

1

Rob - 17/12/07

Thanks for the suggestion although I don't feel comfortable using dates in mm/dd/yyyy format (8/16/2005) since it depends too much on connection settings. Because in some countries dd/mm/yyyy (16/08/2005) is used.Universal format yyyy/mm/dd makes sorting also easier.

» Report offensive content

2

Mahesh - 17/12/07

Under Searching for Rows, u have mentioned, instead using IN use BETWEEN so in that case query optimizer will use Index. But if I have to search strings, then?

i.e. Select Id, Name From Tab Where Name In ('A', 'B', 'C')

Thanks in advance,

Mahesh

» Report offensive content

3

Praveen Gupta - 17/12/07

Don't you think that record search using date will not be possible, if date format used is not mm/dd/yyyy, as you have said in your article.

» Report offensive content

4

Sean M - 17/12/07

Nice!
You could also mention the use of DISTINCT. In my experience distinct is used to cover up a problem with a join that someone doesn't really want to spend the time looking for.

» Report offensive content

5

Lee Shuster - 18/12/07

I think your information on using IN() is a bit off the mark. I use IN()'s every where & they always go through the index. I believe I would know if it didn't as the table has 3.5m records.

» Report offensive content

6

T Man - 18/12/07

I think these tips give one a better understanding and some insight into how queries are evaluated. They provide pointers to what to look for when searching for improved query performance.

One cannot expect to have every example spelled out here but the pointers are most useful, thanks.

» Report offensive content

7

zefuzhang - 18/12/07

In SQLServer 2005,it looks using the index when the statement with '<>, OR, NOT IN'

select stor_id,qty from dbo.sales --Pubs Database
where qty<>20
plan_text:
|--Index Seek(OBJECT:([pubs].[dbo].[sales].[idx_qty]), SEEK:([pubs].[dbo].[sales].[qty] < (20) OR [pubs].[dbo].[sales].[qty] > (20)) ORDERED FORWARD)

select stor_id,qty from dbo.sales
where qty=20 or qty=10
plan_text:
|--Index Seek(OBJECT:([pubs].[dbo].[sales].[idx_qty]), SEEK:([pubs].[dbo].[sales].[qty]=(10) OR [pubs].[dbo].[sales].[qty]=(20)) ORDERED FORWARD)

is it true?

» Report offensive content

8

Jitendra Sali - 18/12/07

nice..its good to improve performance

» Report offensive content

9

Giorgio - 18/12/07

Well, that one instead using IN use BETWEEN does not work for most people because most aren't contiguous! A lot of people use this type of filtering where id in (select id from table1 where something = something)
Obviously Between doesn't work here so what is your solution for this?

» Report offensive content

10

Sharon Matyk - 19/12/07

erm ... why not just sale SaleDate='8/15/2007' ? Or convert(char(10),SaleDate,103)='08/15/2007' ?

Why would it be a good thing to do >=15th and <16th ... how is that faster?

» Report offensive content

11

Asier - 21/12/07

To avoid the problem with dates (comments #1 and #3) I suggest you the following statement:

SELECT SaleID
FROM SalesHistory
WHERE
SaleDate >= { d '2005-08-15' } AND
SaleDate < { d '2005-08-15' }

» Report offensive content

12

Terence James - 27/12/07

You should add one to the last date to compare

SELECT SaleID
FROM SalesHistory
WHERE
SaleDate >= { d '2005-08-15' } AND
SaleDate < { d '2005-08-16' }

» Report offensive content

13

VeKrabowitz - 05/01/08

I've tried the in and or statements. They both result in an index seek - albeit 2 separate ones (seems to result in an index scan in SQL 2000, which is still better than a table scan).
Seems to me that using OR and IN do not necessarily result in the SQL engine ignoring indexes. Can anyone please confirm??

» Report offensive content

14

Shavantha - 09/01/08

This is really good... even most of developers known this worth to share it :-)

» Report offensive content

15

Michael Clark - 15/03/08

For the date query why did you not use a BETWEEN statement?

SELECT SaleID
FROM SalesHistory
WHERE
SaleDate BETWEEN '8/15/2005' AND '8/16/2005'

» Report offensive content

Leave a comment

You must read and type the 6 chars within 0..9 and A..F

* indicates mandatory fields.

15

Michael Clark - 15/03/08

For the date query why did you not use a BETWEEN statement? SELECT SaleID FROM SalesHistory WHERE SaleDate BETWEEN '8/15/2005' AND '8/16/2005' ... more

14

Shavantha - 01/09/08

This is really good... even most of developers known this worth to share it :-) ... more

13

VeKrabowitz - 01/05/08

I've tried the in and or statements. They both result in an index seek - albeit 2 separate ones (seems to ... more

Log in


Sign up | Forgot your password?

  • Chris Duckett IE9's H.264 vote killed Ogg

    In a split decision by the judges, the winner of the W3C/WHATWG video codec consensus is H.264, taking home the future of video playback on the internet while loser Ogg goes home with nothing but thoughts of what might have been. Read more »

    -- posted by Chris Duckett

  • Staff Google launches Apps Marketplace

    Google launches and app store, while Mozilla plans to re-write its open-source license. More of this week's news in the Roundup. Read more »

    -- posted by Staff

  • Staff Microsoft showcases new NUIs

    TechFest, Microsoft's internal even took place this week with researchers showcasing some new interfaces the company is working on. Read more »

    -- posted by Staff

What's on?

  • Optus Deal

    Broadband + home phone + PlayStation®3 in a single package price!