Conceptually the leaf level in a non-filtered, non-clustered index in SQL Server has 1 row of data per row in the underlying table. The columns in the leaf level are the distinct columns from the following:
- Columns that make up the index key. (So we can navigate the index)
- A conceptual pointer to the corresponding row in the base table. (So we can get back to the corresponding row in the base table)
- For a heap, the pointer is the RID, or row identifier
- For a Clustered Index, the pointer is the key columns that make up the clustered index
- Any included Columns (Extra columns stuck in for good measure)
For example:
CREATE TABLE t1 (id int not null, first_name varchar(20), last_name varchar(20))
CREATE CLUSTERED INDEX CIX_t1 on t1 (id)
CREATE INDEX IX_t1_a on t1 (first_name)
CREATE INDEX IX_t1_b on t1 (first_name) INCLUDE (id)
CREATE INDEX IX_t1_c on t1 (first_name) INCLUDE (id, last_name)
CREATE INDEX IX_t1_d on t1 (first_name, last_name)
CREATE INDEX IX_t1_e on t1 (first_name, id)
The leaf level of IX_t1_a consists of (first_name, id)
The leaf level of IX_t1_b consists of (first_name, id)
The leaf level of IX_t1_c consists of (first_name, id, last_name)
The leaf level of IX_t1_d consists of (first_name, id, last_name)
The leaf level of IX_t1_e consists of (first_name, id)
Columns are never included twice. In the example above, indexes a,b,c are duplicates of each other. Likewise, indexes c and d are duplicates as well. (There are subtle differences in the non-leaf levels depending on the uniqueness of clustered and non-clustered indexes, but for which queries the index can be used for, they are identical.)