Create more than one non clustered index on same column in SQL Server

What is the index creating strategy?

Is it possible to create more than one non-clustered index on the same column in SQL Server?

How about creating clustered and non-clustered on same column?

Very sorry, but indexing is very confusing to me.

Is there any way to find out the estimated query execution time in SQL Server?

Answers


The words are rather logical and you'll learn them quite quickly. :)

In layman's terms, SEEK implies seeking out precise locations for records, which is what the SQL Server does when the column you're searching in is indexed, and your filter (the WHERE condition) is accurrate enough.

SCAN means a larger range of rows where the query execution planner estimates it's faster to fetch a whole range as opposed to individually seeking each value.

And yes, you can have multiple indexes on the same field, and sometimes it can be a very good idea. Play out with the indexes and use the query execution planner to determine what happens (shortcut in SSMS: Ctrl + M). You can even run two versions of the same query and the execution planner will easily show you how much resources and time is taken by each, making optimization quite easy.

But to expand on these a bit, say you have an address table like so, and it has over 1 billion records:

CREATE TABLE ADDRESS 
  (ADDRESS_ID INT -- CLUSTERED primary key ADRESS_PK_IDX
  , PERSON_ID INT -- FOREIGN KEY, NONCLUSTERED INDEX ADDRESS_PERSON_IDX
  , CITY VARCHAR(256)
  , MARKED_FOR_CHECKUP BIT
  , **+n^10 different other columns...**)

Now, if you want to find all the address information for person 12345, the index on PERSON_ID is perfect. Since the table has loads of other data on the same row, it would be inefficient and space-consuming to create a nonclustered index to cover all other columns as well as PERSON_ID. In this case, SQL Server will execute an index SEEK on the index in PERSON_ID, then use that to do a Key Lookup on the clustered index in ADDRESS_ID, and from there return all the data in all other columns on that same row.

However, say you want to search for all the persons in a city, but you don't need other address information. This time, the most effective way would be to create an index on CITY and use INCLUDE option to cover PERSON_ID as well. That way, a single index seek / scan would return all the information you need without the need to resort to checking the CLUSTERED index for the PERSON_ID data on the same row.

Now, let's say both of those queries are required but still rather heavy because of the 1 billion records. But there's one special query that needs to be really really fast. That query wants all the persons on addresses that have been MARKED_FOR_CHECKUP, and who must live in New York (ignore whatever checkup means, that doesn't matter). Now you might want to create a third, filtered index on MARKED_FOR_CHECKUP and CITY, with INCLUDE covering PERSON_ID, and with a filter saying CITY = 'New York' and MARKED_FOR_CHECKUP = 1. This index would be insanely fast, as it only ever cover queries that satisfy those exact conditions, and therefore has a fraction of the data to go through compared to the other indexes.

(Disclaimer here, bear in mind that the query execution planner is not stupid, it can use multiple nonclustered indexes together to produce the correct results, so the examples above may not be the best ones available as it's very hard to imagine when you would need 3 different indexes covering the same column, but I'm sure you get the idea.)

The types of index, their columns, included columns, sorting orders, filters etc depend entirely on the situation. You will need to make covering indexes to satisfy several different types of queries, as well as customized indexes created specifically for singular, important queries. Each index takes up space on the HDD so making useless indexes is wasteful and requires extra maintenance whenever the data model changes, and wastes time in defragmentation and statistics update operations though... so you don't want to just slap an index on everything either.

Experiment, learn and work out which works best for your needs.


I'm not the expert on indexing either, but here is what I know.

A very important point to remember is that Indexes although it makes your select faster, influence your Insert/Update/Delete speed as the information needs to be added to the index, which means that the more indexes you have on a column that gets updated a lot, will drastically reduce the speed of the update.

You can include columns that is used on a CLUSTERED index in one or more NON-CLUSTERED indexes.

Here is some more reading material

http://www.sqlteam.com/article/sql-server-indexes-the-basics http://www.programmerinterview.com/index.php/database-sql/what-is-an-index/

EDIT

Another point to remember is that an index takes up space just like the table. The more indexes you create the more space it uses, so try not to use char/varchar (or nchar/nvarchar) in an index. It uses to much space in the index, and on huge columns give basically no benefit. When your Indexes start to become bigger than your table, it also means that you have to relook your index strategy.


Need Your Help

Disposing objects in the Destructor

c# dispose idisposable

I have an object that has a disposable object as a member.

show and hide Javascript (display:none) issue

javascript jquery html css

I have created a show/hide javascript function which seems to work perfectly - When you click on the link it reveals the gif version of the logo.