Composite Non-Clustered Indexes – does the Column Order matter?

(Be sure to checkout the FREE SQLpassion Performance Tuning Training Plan - you get a weekly email packed with all the essential knowledge you need to know about performance tuning on SQL Server.)

When I talk about indexes, people always ask me if the sorting order of the columns in a composite Non-Clustered Index matters? The short answer is always “It depends”. Let’s have a look on it why “it depends”..

Singleton Lookups

When you have queries which perform Singleton Lookups on your tables, the sorting order of the columns in a composite Non-Clustered Index doesn’t really matter. Imagine the following query:

You can now create a Non-Clustered Index on StateProvinceID and City, or on City and StateProvinceID:

The ordering of the columns in the Non-Clustered Index doesn’t really matter here, because SQL Server will just perform a simple Non-Clustered Index Seek operation (in combination with a Seek Predicate) in the execution plan:

There is only a Seek Predicate used

Range Scans

Things change when we talk about Range Scans on tables, where you retrieve a set of data. Imagine you execute the following query:

Again, you have 2 choices for a supporting Non-Clustered Index:

  • Non-Clustered Index on StateProvinceID and City
  • Non-Clustered Index on City and StateProvinceID

Let’s create the first choice:

In that case, SQL Server performs for the query a Non-Clustered Index Seek operation on the column StateProvinceID, and has to evaluate a Residual Predicate for the column City as you can see in the generated execution plan:

Now we have a Seek Predicate and a Residual Predicate!

This is not really a perfect execution plan, because you are reading physically more data than you have logically requested. But with the sorting order based on StateProvinceID as a leading column and City as a subsequent column this is the only possible behavior as you can see from the following picture:

Our data is in the wrong sorting order

But let’s try now to create the Non-Clustered Index where we just swap the columns: the City column as a leading column, and the column StateProvinceID as the second one:

When you now execute your query again, you can see that SQL Server again performs a Non-Clustered Index Seek operation. But this time you have *no* Residual Predicate for your query.

Now there is only a Seek Predicate

Therefore you are physically reading just those rows that you logically requested. But how is this now possible? Just have a look at the following picture that shows you how the data is currently sorted in the Non-Clustered Index:

Our data is now in the correct sorting order

As you can see the data is now presorted on City, and within each City group you have presorting on the column StateProvinceID. Therefore you can get straight to those records that you logically requested – and return them without any further evaluating of a Residual Predicate!

Summary

The column ordering in a composite Non-Clustered Index matters – when you have to perform Range Scans! As I’m always saying in my various workshops: almost everything in SQL Server is about Indexing, and Indexing itself is just presorting data! Nothing more! To understand whether SQL Server can directly seek to logically requested records, you also have to visualize in your mind how the data is presorted, and how you can access it by presorting the data efficiently.

I hope that this blog posting gave you a better understanding of how the column ordering in a Non-Clustered Index influences a Seek operation.

Like or share to get the source code.

Thanks for your time,

-Klaus

3 Comments

  • Andrzej Jasinski

    Great article, however title is misleading – it`s not about Sorting Order (ASC/DESC), but about column order. It might be interesting to see if sorting order could matter.

    Regards,
    Andrzej

    • Klaus Aschenbrenner

      Hello Andrzej,

      Thanks for your comment.
      Aaah, you are right, the title of the blog posting could be better 😉
      I have changed it now!

      Thanks for the input,

      -Klaus

  • Varun Dhawan

    Good insight on index / query plan behaviour. Thanks Klaus

It`s your turn

Your email address will not be published. Required fields are marked *

SQLpassion

Copyright © 2015 by SQLpassion · Klaus Aschenbrenner · Imprint · Offerings · Academy · Contact · Go to Top