Today I came across very interesting observation while I was working on query optimization. Let us run the example first. Make sure to to enable Execution Plan (Using CTRL + M) before running comparison queries.
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.
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
Clean up the database by running following script.
/*Clean up */ DROP TABLE [dbo].[MyTable] GO
Interesting part of above execution plan is now both queries are using nonclustered index scan. Logically first query should have not used index which is for second query as it was retrieving the column which was not in the nonclustered index. However, it did used the nonclustered index and only difference between our first execution and second execution is that we have created clustered index over the column which is retrieved in the first query.
The question is : The question is why this has happened?
In summary : A query which is not using nonclustered index to retrieve results used nonclustered index when clustered index created on the column which is retrieved.
The reason for this happening 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 case as column on which clustered index is created is in SELECT clause and WHERE clause contains columns which are used in nonclustered index.
Let me know what do you think about this article. It may be possible I have not explained this problem properly so I suggest if my readers can rewrite this part of problem and send it to me and I can include their documentation here.
Reference : Pinal Dave (https://blog.sqlauthority.com)