What I really mean is...
There is no difference between a clustered index and the table itself.
Isn't a clustered index assigned to fields? For example, if I have 20 columns in a table and the clustered index is on first name and last name aren't the rest of the columns being sorted on the first name and last name?
In any index, the data is sorted based on the index keys.
With a clustered index, the other 18 columns are included in the index data (but not used for sorting).
With a non-clustered index, only the index keys and any included columns are stored in the index.
Maybe an example would help. Suppose you had this table.
[tt]
People
PersonId FirstName LastName ShoeSize EyeColor
1 George Washington 9 Blue
2 Abraham Lincoln 11 Brown
3 Theodore Roosevelt 8.5 Brown
[/tt]
If you had a clustered index on FirstName,LastName the data in the clustered index would look like this.
[tt]
PersonId FirstName LastName ShoeSize EyeColor
2 Abraham Lincoln 11 Brown
1 George Washington 9 Blue
3 Theodore Roosevelt 8.5 Brown
[/tt]
If you had a non-clustered index on ShoeSize, the data would look like this:
[tt]
PersonId ShoeSize
3 8.5
1 9
2 11
[/tt]
I'm lying a little here because the PersonId isn't necessarily stored in the non-clustered index, but there is an extra piece of data there that points back to the original table.
Anyway, the point is, with a clustered index, all of the data in the table is included in the index because the table itself and the clustered index are really the same thing (under the SQL Server hood).
With a non-clustered index, there is a row pointer (similar to the personid) and the data in the index key columns.
--------------------------
In my database, I have a MapStreets table with 30,000 rows. This data is primarily read from, so I have a lot of indexes on this table. When I run the following code....
Code:
SELECT i.name AS IndexName,
SUM(page_count * 8) AS IndexSizeKB
FROM sys.dm_db_index_physical_stats(
db_id(), object_id('[!]dbo.MapStreets[/!]'), NULL, NULL, 'DETAILED') AS s
Inner JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id]
AND s.index_id = i.index_id
GROUP BY i.name
exec sp_spaceused '[!]MapStreets[/!]'
The output is this...
[tt]
IndexName IndexSizeKB
------------------------------------------------ -----------
idx_mapStreets_EndLatitude 464
idx_MapStreets_EndLongitude 464
idx_MapStreets_MajorClassification_FeatureId 344
idx_MapStreets_StartLatitude 464
idx_MapStreets_StartLongitude 464
MapStreets_Distance 464
MapStreets_FeatureIdMajorClassification 344
MapStreets_FromNode 856
MapStreets_ToNode 584
MapStreets12 856
PK_MapStreets 3264
--------------
name rows reserved data index_size unused
----------- ------- -------- -------- ---------- -------
MapStreets 30465 9752 KB 3256 KB 5400 KB 1096 KB
[/tt]
Notice the index named PK_MapStreets. This is the clustered index, and it is (roughly) the same size as the table data. There are slight differences in the calculations to account for the minor differences.
If you add up the index sizes for all the non-clustered indexes, you get 5304 which is roughly the same as the index_size column (rounding errors and such).
Does this help you to understand?
-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom