+1  A: 

SQLServer (or any other SQL Server product for that matter) if not forced to use any index at all. It will use it, if it thinks will help running the query more efficiently.

So, in your case, SQLServer is thinking that it doesn't need using IX_PhoneStatus_PhoneID and by using its clustered index might get better results. It might be wrong though, that's what index hints are for: letting the Server know it would do a better job by using other index.

If your table was recently created and populated, it might be the case that statistics are somewhat outdated. So you might want to force a statistic update.

Pablo Santa Cruz
+2  A: 

Take a look at Is an index seek always better or faster than an index scan? Sometimes a seek and a scan will be the exact same.

An index might be disregarded because your stats could be stale or the selectivity of the index is so low that SQL Server thinks a scan will be better

Turn on stats and see if there are any differences between the query with and without a seek

SET STATISTICS io ON
UPDATE PhoneStatus
SET RecordEndDate = GETDATE()
WHERE PhoneID = 126


UPDATE PhoneStatus
SET RecordEndDate = GETDATE()
FROM Cust_Profile.PhoneStatus WITH(INDEX(IX_PhoneStatus_PhoneID))
WHERE PhoneID = 126

Now look at the reads that came back

SQLMenace
PhoneStatus is the name of his table, not column. So I don't think this is not his case.
Pablo Santa Cruz
Would that be the case, I think the order of the index is OK, if it was in the wrong order even a hint wouldn't help.
Paul Hadfield
Okay will update the answer
SQLMenace
+2  A: 

Pablo is correct, SQL Server will use an index only if it thinks this will run the query more efficiently. But with 20 million rows it should have known to use the index. I would imagine that you simply need to update statistics on the database.

Form more information, see http://msdn.microsoft.com/en-us/library/aa260645(SQL.80).aspx.

Russ
+2  A: 

How many distinct PhoneIDs are in the 20M table? If the condition where PhoneID=126 is not selective enough, you may be hitting the index tipping point. If this query and access condition is very frequent, PhoneID is a good candidate for a clustered index leftmost key.

Remus Rusanu
Quick comment about a clustered index. With 20 million rows, if you insert data and the table has a clustered index, you may see a reasonable delay whilst the table re-organises itself to reflect the clustered index.
Paul Hadfield
The PhoneID is very unique. In the table of 20 million records, each phoneID could show up 10 times at the most.
BarDev
You can use the tips from this post to understand what rules are being applied that result in the wrong plan: see http://sqlblog.com/blogs/paul_white/archive/2010/07/31/inside-the-optimiser-constructing-a-plan-part-3.aspx
Remus Rusanu
I went back and looked at the query again and noticed that the problem was only occurring in UAT. Production seems to be running fine. Also UAT has a very small set of data. So I believe the first query does not use the Index because of the limited number of rows in UAT. I will test this theory and put more records in UAT to test this scenario.
BarDev
A: 

To restate:

  • You have table PhoneStatus
  • With a clustered index
  • And a non-clustered index on columns PhoneStatus and PhoneId, in that order
  • You are issuing an update with "...WHERE PhoneId = 126"
  • There are 20 million rows in the table (i.e. it's big and then some)

SQL will take your query and try to figure out how to do the work without working over the whole table. For your non-clustered index, the data might look like:

PhoneStatus  PhoneID
  A            124
  A            125
  A            126
  B            127
  C            128
  C            129
  C            130
 etc.

The thing is, SQL will check the first column first, before it checks the value of the second column. As the first column is not specified in the update, SQL cannot "shortcut" through the index search tree to the relevant entries, and so will have to scan the entire table. (No, SQL is not clever enough to say "eh, I'll just check the second column first", and yes, they're right to have done it that way.)

Since the non-clustered index won't make the query faster, it defaults to a table scan -- and since there is a clustered index, that means it instead becomse a clustered index scan. (If the clustered index is on PhoneId, then you'd have optimal performance on your query, but I'm guessing that's not the case here.)

When you use the hint, it forces the use the non-clustered index, and that will be faster than the full table scan if the table has a lot more columns than the index (which essentially has only the two), because there'd be that much less data to sift through.

Philip Kelley
The non-cluster index only includes PhoneID.
BarDev