This 2007 White Paper compares the performance for individual select/insert/delete/update and range select statements on a table organized as a clustered index vs that on a table organized as a heap with a non clustered index on the same key columns as the CI table.
Generally the clustered index option performed better in the tests as there is only one structure to maintain and because there is no need for bookmark lookups.
One potentially interesting case not covered by the paper would have been a comparison between a non clustered index on a heap vs a non clustered index on a clustered index. In that instance I would have expected the heap might even perform better as once at the NCI leaf level SQL Server has a RID to follow directly rather than needing to traverse the clustered index.
Is anyone aware of similar formal testing that has been carried out in this area and if so what were the results?
To check your request I created 2 tables following this scheme:
The first table called
heap
got a non clustered index on the fieldgroup
. The second table calledclust
got a clustered index on the sequential field calledkey
and a nonclustered index on the fieldgroup
The tests were run on an I5 M540 processor with 2 hyperthreaded cores, 4Gb memory and 64-bit windows 7.
SELECT performance
To check performanc numbers I performed the following queries once on the heap table and once on the clust table:
The results of this benchmark are for the
heap
:for the table
clust
the results are:SELECT WITH JOIN performance
cmd.CommandText = "select * from heap/clust h join keys k on h.group = k.group where h.group between @id and @id+1000";
The results of this benchmark are for the
heap
:873 Rows have > 0 CPU and affect more than 0 rows
The results of this benchmark are for the
clust
:865 Rows have > 0 CPU and affect more than 0 rows
UPDATE performance
The second batch of queries are update statements:
the results of this benchmark for the
heap
:the results of this benchmark for the
clust
:DELETE benchmarks
the third batch of queries I ran are delete statements
The result of this benchmark for the
heap
:the result of this benchmark for the
clust
:INSERT benchmarks
The last part of the benchmark is the execution of insert statements.
insert into heap/clust (...) values (...), (...), (...), (...), (...), (...)
The result of this benchmark for the
heap
:The result of this benchmark for the
clust
:Conclusions
Although there are more logical reads going on when accessing the table with the clustered & the nonclustered index (while using the nonclustered index) the performance results are:
Of course my benchmark was very limited on a specific kind of table and with a very limited set of queries, but I think that based on this information we can already start saying that it is virtually always better to create a clustered index on your table.
As we can see from the added results, the conclusions on the limited tests were not correct in every case.
The results now indicate that the only statements which benefit from the clustered index are the update statements. The other statements are about 30% slower on the table with clustered index.
Some additional charts where I plotted the weighted duration per query for heap vs clust.
As you can see the performance profile for the insert statements is quite interesting. The spikes are caused by a few data points which take a lot longer to complete.