问题
i have a table on SQL Server with about 1 million rows. It has an ID (PK), a status (int) and a datetime column. Also I've created an Index on the datetime column.
Now I've found out an effect, which I don't understand.
SELECT status
FROM table
WHERE dateTime BETWEEN '2010-01-01T00:00:00' AND '2010-01-02T12:00:00'
This statement returns 3664 rows. It runs about 150ms and the execution plan shows that its doing an index seek with key lookup.
Now, if I change it as following (just change the hour from 12 to 13):
SELECT status
FROM table
WHERE dateTime BETWEEN '2010-01-01T00:00:00' AND '2010-01-02T13:00:00'
This statement returns 3667 rows. It runs about 600ms and the exuction plan shows that its using the primary key!
I just don't understand it. For 3667 and more rows its always using the primary key, even if the seek is much faster.
Is there an explanation?
回答1:
status
is not included in the index on datetime
so it needs to do key lookups for each matching row to retrieve this value.
As the range grows (and hence number of lookups required) it estimates that it will be quicker just to scan the whole (covering) clustered index avoiding the lookups. Possibly incorrectly in your case. The point at which it switches from one plan to the other is known as the tipping point.
You should check if the estimated vs actual number of rows is out of whack (perhaps some rows that would have matched the range have been deleted since the statistics were last updated).
Or maybe the index scan is more expensive than the costing assumptions assume due to high levels of fragmentation or for some other reason the costing assumptions made do not reflect the actual relative performance in your environment.
来源:https://stackoverflow.com/questions/12846283/why-is-sql-server-not-using-index-for-very-similar-datetime-query