Quantcast
Channel: Journey to SQL Authority with Pinal Dave » SQL Constraint and Keys
Viewing all articles
Browse latest Browse all 32

SQL SERVER – Observation – Effect of Clustered Index over Nonclustered Index

$
0
0

Note: This article is re-write of my previous article SQL SERVER – Observation – Effect of Clustered Index over Nonclustered Index. I have received so many request that re-write it as it is little confusing. I am going to re-write this with simpler words.

Query optimization is one art which is difficult to master. Just like any other art this requires creativity and imagination as well understanding of subject matter. Let us look at interesting observation which I came across.

First of all download the script from here and run it in SSMS.

Now enable Execution Plan (Using CTRL + M) in SSMS before running the script.

The simple objective of this whole exercise is to understand how clustered index and nonclustered indexes are associated with each other.

In our example we have one query which is not using any index. On the same table there is already nonclustered index created, which is also not being used. Now when we created clustered index on the same table, our query suddenly started to use nonclustered index which was so far it is not using. The interesting part of this is that query is using nonclustered index when clustered index is created on the same.

Now let us test the same thing with example.

USE [AdventureWorks]
GO
/* */
CREATE TABLE [dbo].[MyTable](
[ID] [int] NOT NULL,
[First] [nchar](10) NULL,
[Second] [nchar](10) NULL
)
ON [PRIMARY]
GO
/* Create Sample Table */
INSERT INTO [AdventureWorks].[dbo].[MyTable]
([ID],[First],[Second])
SELECT 1,'First1','Second1'
UNION ALL
SELECT 2,'First2','Second2'
UNION ALL
SELECT 3,'First3','Second3'
UNION ALL
SELECT 4,'First4','Second4'
UNION ALL
SELECT 5,'First5','Second5'
GO

Now let us create nonclustered index over this table.

/* Create Nonclustered Index over Table */
CREATE NONCLUSTERED INDEX [IX_MyTable_NonClustered]
ON [dbo].[MyTable]
(
[First] ASC,
[Second] ASC
) ON [PRIMARY]
GO

Run following two queries together.

/* Run following two queries together and observe the
result in by Enabling Actual Execution Plan (CTRL + M)
1st Query will use Table Scan
2nd Query will use Index Seek
*/
SELECT ID
FROM [MyTable]
WHERE First = 'First1' AND Second = 'Second1'
SELECT Second
FROM [MyTable]
WHERE First = 'First1' AND Second = 'Second1'
GO

It is clear from query that index applies to columns on which it is created. In our case as in WHERE condition we have same columns which are used in Index.
Query 1 – Does not use any index
Query 2 – Does nonclustered index seek

Now create Clustered Index over the same table.

/* Create Clustered Index over Table */
CREATE CLUSTERED INDEX [IX_MyTable_Clustered]
ON [dbo].[MyTable]
(
[ID] ASC
) ON [PRIMARY]
GO

Once again run above two same query and see the execution plan.

/* Run following two queries together and observe the
result in 1st Query will use Index Seek
2nd Query will use Index Seek
*/
SELECT ID
FROM [MyTable]
WHERE First = 'First1' AND Second = 'Second1'
SELECT Second
FROM [MyTable]
WHERE First = 'First1' AND Second = 'Second1'
GO

Query 1 – Does nonclustered index seek
Query 2 – Does nonclustered index seek

Clean up the database by running following script.

/* Clean up */
DROP TABLE [dbo].[MyTable]
GO

Let us go over our steps of whole exercise.
Step 1: We have one table and one nonclustered index.
Step 2: We ran Query 1 which does not use nonclustered index.
Step 3: We created clustered index over table.
Step 4: We ran Query 1 which now use nonclustered index.

What is puzzling and interesting is how come query suddenly started to use nonclustered query when clustered index is created on table?

Query 1 should not have used index which is for second query as there is no change in that index or query1. Additionally, Query 1 is not even retrieving the column which is in nonclustered index. We created clustered index on column used in Query 1, so it should make Query 1 to use that clustered index but instead it is using nonclustered index which was already created and available to use earlier.

The question is : The question is why this has happened? If Query can use nonclustered index why did it has to wait for clustered index to be created?

Answer:
The reason for this is that every nonclustered index refers to clustered index internally. When clustered index is created on table it reorganizes the table in the physical order of the clustered index. When there is no clustered index created on table at that time all nonclustered index points to data in the table to retrieve the data, however once clustered index is created all the nonclustered indexes are reorganized and they point to clustered index. This effect is creating index seek operation on nonclustered index. In our example column on which clustered index is created is in SELECT clause and WHERE clause contains columns which are used in nonclustered index, which is creating the effect which we have observed.

Let me know what do you think about this re-written article, it should be clear now what I am trying to suggest. Again, I am looking forward to your feedback about this subject. I will be discussing this in next UG meeting which is today. Please leave a not to me and we can go over this article on goto meeting or live meeting.

Reference: Pinal Dave (http://blog.SQLAuthority.com)


Posted in Pinal Dave, SQL, SQL Authority, SQL Constraint and Keys, SQL Index, SQL Optimization, SQL Performance, SQL Query, SQL Scripts, SQL Server, SQL Tips and Tricks, T SQL, Technology

Viewing all articles
Browse latest Browse all 32

Trending Articles