[quoted text, click to view] mchi55@hotmail.com wrote:
> I have a table with 220000 rows.
>
> There is a column called status_id. I have a nonclustered index on
> statusid.
>
> if I do a
>
> select from table
> where status_id = 161
>
> I get a table scan with the non clusteredindex.
> There are about 16000 records with a status_id of 161. This there no
> way to avoid the table scan since there are so many records? Why is
> it not using the index?
> select *
> where status_id = 161 also takes like 2 minutes to run.
>
> If I place a clustered index on status_id...the query returns in a
> split second and uses a clustered index seek.
> For production purposes...I can't place the clustered index on
> status_id.
>
> What can I do?
>
> Also...the table has about 200 rows...completely unnormalized and a
> mess.
>
It's because you're using SELECT *. You're telling the query to return
every field for the matching rows. Let's look at a different variation
of your query:
SELECT status_id, someothercolumn
FROM table
WHERE status_id = 161
If you look at the execution plan for this query, you'll see that it
(probably) does an index seek using your nonclustered index, followed by
a bookmark lookup. It uses the index to locate records matching the
status_id filter, but because the index doesn't include the
"someothercolumn" column, it has to go to the table (using a bookmark
lookup) to get that value.
Now, back to your example:
SELECT *
FROM table
WHERE status_id = 161
You've just asked it to return EVERY column for every row matching your
filter condition. Because the index doesn't include EVERY column, a
large bookmark lookup will have to be done to get all of those values.
The query engine has determined that it is "cheaper" to just scan the
table and grab everything in one pass, rather than use the index, then
make a seperate trip to the table to get the other values.
With a clustered index, the index *IS* the table, so there's no need to
make a return trip to do a bookmark lookup.
Does that help?
--
Tracy McKibben
MCDBA