8.3 SQL Server非聚集索引
SQL Server Non-Clustered Indexes(非聚集索引)
简介
非聚集索引是一种数据结构,可以提高查询速度。与聚集索引不同,非聚集索引将索引数据与表中的数据行分开进行排序和存储。它是表中选定数据列的副本,其中包含指向关联表的链接。
与聚集索引类似,非聚集索引使用B+树结构来组织其数据。
一个表可以有一个或多个非聚集索引,每个非聚集索引可以包含表的一列或多列。
下图说明了非聚集索引的结构:
除了存储索引键值,叶节点还存储指向数据行的行指针。这些行指针也称为行定位器。
如果基础表包含聚集索引,则行指针是聚集索引的键,如果基础表未包含索引(底层还是无序的堆结构),则行指针指向表的行。
使用SQL Server CREATE [NONCLUSTERED] INDEX创建非聚集索引
语法:
| CREATE [NONCLUSTERED] INDEX index_name | |
| ON table_name(column_list); |
此语法中:
- 首先,在
CREATE NONCLUSTERED INDEX子句后面指定索引的名字,NONCLUSTERED关键字可以省略 - 其次,指定要在其上创建索引的表名和该表的列列表作为索引键列。
示例
有如下客户表

因为客户表有主键customer_id,所以是一张聚集表,
A)使用CREATE INDEX语句在一列上添加一个聚集索引
语句查找在阿特沃特的客户:
| SELECT | |
| customer_id, | |
| city | |
| FROM | |
| sales.customers | |
| WHERE | |
| city = 'Atwater'; |
如果打开执行计划,你将看到查询优化器是聚集索引扫描(Scan)来查找行,这是因为customers表中没有为city列建索引

要提高查询速度,你可以给city列添加索引:
| CREATE INDEX ix_customers_city | |
| ON sales.customers(city); |
此时如果再打开执行计划,将会发现查询优化器使用的是非聚集索引(ix_customers_city:)查找(Seek):

B)使用CREATE INDEX语句在多列上添加一个聚集索引
查找姓是伯格,并且名是Monika的客户:
| SELECT | |
| customer_id, | |
| first_name, | |
| last_name | |
| FROM | |
| sales.customers | |
| WHERE | |
| last_name = 'Berg' AND | |
| first_name = 'Monika'; |

查询优化器扫描聚集索引来定位客户。
要提高查询速度,你可以创建包含last_name和first_name两列的一个非聚集索引:
| CREATE INDEX ix_customers_name | |
| ON sales.customers(last_name, first_name); |
现在,查询优化器就会使用索引ix_customers_name来查找客户。
| SELECT | |
| customer_id, | |
| first_name, | |
| last_name | |
| FROM | |
| sales.customers | |
| WHERE | |
| last_name = 'Berg' AND | |
| first_name = 'Monika'; |

创建由多个列组成的非聚集索引时,索引中列的顺序非常重要。您应该将经常用于查询数据的列放在列的开头。
例如,以下查找姓氏(last_name)为Albert的客户。因为last_name是索引中最左边的列,所以查询优化器可以利用索引并使用索引查找方法进行搜索:
| SELECT | |
| customer_id, | |
| first_name, | |
| last_name | |
| FROM | |
| sales.customers | |
| WHERE | |
| last_name = 'Albert'; |

此语句查找名(first_name)为Adam的客户,它也用到了ix_customer_name索引。但它需要扫描(Scan)整个索引进行搜索,这比索引查找(Seek)慢。
| SELECT | |
| customer_id, | |
| first_name, | |
| last_name | |
| FROM | |
| sales.customers | |
| WHERE | |
| first_name = 'Adam'; |

因此,最好将经常用于查询数据的列放在索引列列表的开头。
浙公网安备 33010602011771号