Sunday, October 28, 2007

Table Scan, Index Scan, Index Seek

Table scan -- searches through every data page in a heap table;

Index scan -- if database engine optimizer finds an index can be used, the engine can scan every index leaf page. Indexes are usually thinner than the base table, so it is cheaper to scan an index.

For example,
SELECT TransactionType
FROM Production.TransactionHistoryArchive;


The database storage engine finds the Clustered Index can be used. Because of no WHERE clause to limit the output of the statement, Clustered Index Scan has to be used.
Index seek - if an index with a matching first column to your query is available, it can use the b-tree structures to get the data row(s) (start --end) . For example,


USE AdventureWorks;
GO
SET NOCOUNT ON;
GO
SET SHOWPLAN_ALL ON;
GO
SELECT NameFROM Production.UnitMeasure
WHERE UnitMeasureCode BETWEEN 'Each' AND 'Inch';
GO
SET SHOWPLAN_ALL OFF;

It is better to have a clustered index in a table. Table scan is the slowest possible way of execution. Table scan means not only that no index is used, but that there is no clustered index for this table at all. Even if you can only replace table scan with clustered index scan, it is still worth it.

If you see clustered index scan, find out whether it can be replaced with index seek. For that, find what conditions are applied to this table. Usually, conditions exist for two or three fields of the table. Find out the most selective condition (that is, the condition that would produce the smallest number of records if applied alone), and see whether an index on this field exists. Any index that lists this field first will qualify.

SQL Server determines whether to use an index by examining only the first column defined in the index. For example,

USE AdventureWorks

GO
CREATE INDEX fl_index
ON Person.Contact(FirstName,LastName)
GO
The following batch will show the index scan is used.
USE AdventureWorks;
GO
SET NOCOUNT ON;
GO
SET SHOWPLAN_ALL ON;
GO
SELECT LastName,FirstName FROM Person.Contact
WHERE LastName LIKE 'M%'
GO
SET SHOWPLAN_ALL OFF;
GO

The following batch will show the index seek is used.
USE AdventureWorks;
GO
SET NOCOUNT ON;
GO
SET SHOWPLAN_ALL ON;
GO
SELECT LastName,FirstName FROM Person.Contact
WHERE FirstName LIKE 'M%'
GO
SET SHOWPLAN_ALL OFF;
GO