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_namefirst_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';

因此,最好将经常用于查询数据的列放在索引列列表的开头。

posted @ 2023-01-30 10:25  平元兄  阅读(1030)  评论(0编辑  收藏  举报