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';
因此,最好将经常用于查询数据的列放在索引列列表的开头。