i’m running into a strange problem in Microsoft SQL Server 2008.
I have a large database (20 GB) with about 10 tables and i’m attempting to make a point regarding how to correctly create indexes.
Here’s my problem: on some nested queries i’m getting faster results without using indexes! It’s close (one or two seconds), but in some cases using no indexes at all seems to make these queries run faster… I’m running a Checkpoiunt and a DBCC dropcleanbuffers to reset the caches before running the scripts, so I’m kinda lost.
What could be causing this?
I know for a fact that the indexes are poorly constructed (think one index per relevant field), the whole point is to prove the importance of constructing them correctly, but it should never be slower than having no indexes at all, right?
EDIT: here’s one of the guilty queries:
SET STATISTICS TIME ON
SET STATISTICS IO ON
USE DBX;
GO
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC FREEPROCCACHE;
GO
SELECT * FROM Identifier where CarId in (SELECT CarID from Car where ManufactId = 14) and DataTypeId = 1
Identifier table:
– IdentifierId int not null
– CarId int not null
– DataTypeId int not null
– Alias nvarchar(300)
Car table:
– CarId int not null
– ManufactId int not null
– (several fields followed, all nvarchar(100)
Each of these bullet points has an index, along with some indexes that simultaneously store two of them at a time (e.g. CarId and DataTypeId).
Finally, The identifier table has over million entries, while the Car table has two or three million
My guess would be that SQL Server is incorrectly deciding to use an index, which is then forcing a bookmark lookup*. Usually when this happens (the incorrect use of an index) it’s because the statistics on the table are incorrect.
This can especially happen if you’ve just loaded large amounts of data into one or more of the tables. Or, it could be that SQL Server is just screwing up. It’s pretty rare that this happens (I can count on one hand the times I’ve had to force index use over a 15 year career with SQL Server), but the optimizer is not perfect.
* A bookmark lookup is when SQL Server finds a row that it needs on an index, but then has to go to the actual data pages to retrieve additional columns that are not in the index. If your result set returns a lot of rows this can be costly and clustered index scans can result in better performance.
One way to get rid of bookmark lookups is to use covering indexes – an index which has the filtering columns first, but then also includes any other columns which you would need in the “covered” query. For example:
covering index would be (my_date, my_string1, my_string2)