聚集索引
聚集索引基本上是一个树状组织的表。与将记录存储在未排序的Heap表空间中不同,聚集索引实际上是具有叶子节点(按群集键列值排序)的B+树索引,存储实际的表记录,如下图所示。
在SQL Server和MySQL中,Clustered Index是默认的表结构。即使表没有主键,MySQL也会添加一个隐藏的集群索引,而SQL Server总是在表有主键列时构建一个集群索引。否则,SQL Server将存储为堆表。
聚集索引可以加速按聚集索引键过滤记录的查询,就像通常的CRUD语句一样。由于记录位于叶节点中,因此在根据记录的Primary Key值定位记录时,不需要额外查找额外的列值。
例如,在SQL Server上执行如下SQL查询:
SELECT PostId, Title
FROM Post
WHERE PostId = ?
您可以看到,执行计划使用群集索引查找操作来定位包含Post记录的叶子节点,并且扫描群集索引节点只需要两个逻辑读取:
|StmtText |
|-------------------------------------------------------------------------------------|
|SELECT PostId, Title FROM Post WHERE PostId = @P0 |
| |--Clustered Index Seek(OBJECT:([high_performance_sql].[dbo].[Post].[PK_Post_Id]), |
| SEEK:([high_performance_sql].[dbo].[Post].[PostID]=[@P0]) ORDERED FORWARD) |
Table 'Post'. Scan count 0, logical reads 2, physical reads 0
非聚簇索引
由于聚集索引通常是使用主键列值构建的,如果您想加快使用其他列的查询速度,那么必须添加次要非聚集索引。
二级索引将在它的叶节点中存储主键值,如下图所示:
因此,如果我们在Post表的Title列上创建一个Secondary Index:
CREATE INDEX IDX_Post_Title on Post (Title)
然后执行下面的SQL查询:
SELECT PostId, Title
FROM Post
WHERE Title = ?
我们可以看到,索引查找操作用于在IDX_Post_Title索引中定位叶子节点,它可以提供我们感兴趣的SQL查询投影:
|StmtText |
|------------------------------------------------------------------------------|
|SELECT PostId, Title FROM Post WHERE Title = @P0 |
| |--Index Seek(OBJECT:([high_performance_sql].[dbo].[Post].[IDX_Post_Title]),|
| SEEK:([high_performance_sql].[dbo].[Post].[Title]=[@P0]) ORDERED FORWARD)|
Table 'Post'. Scan count 1, logical reads 2, physical reads 0
由于相关的PostId主键列值存储在IDX_Post_Title叶节点中,因此此查询不需要额外查找来定位聚集索引中的Post行。