8.5 SQL Server覆盖索引

SQL Server覆盖索引

简介

本文使用sales.customers表作为示例

下面语句在email列创建唯一约束:

CREATE UNIQUE INDEX ix_cust_email
ON sales.customers(email);

查找电子邮件为“aide.franco@msn.com”的客户:

SELECT
customer_id,
email
FROM
sales.customers
WHERE
email = 'aide.franco@msn.com';

打开执行计划,您会发现查询优化器使用的是非聚集索引查找(Index Seek)操作,这样的查找性能来很高。

然而,请看下面语句:

SELECT
first_name,
last_name,
email
FROM
sales.customers
WHERE email = 'aide.franco@msn.com';

在这个执行计划中:
首先,查询优化器使用email列的非聚集索引ix_cust_email上的索引查找来查找emailcustomer_id

其次,查询优化器使用sales.customers表的聚集索引的键查找。按客户id(customer_id)查找客户的名字(first_name)和姓氏(last_name)。

总之就是,对于在非聚集索引中找到的每一行,它使用嵌套循环与聚集索引中发现的行相匹配。

可以清晰的看到,键查找的开销约为查询的50%,这个开销很大。

为了帮助减少这种键查找开销,SQL Server可以通过包含非键列来增加非聚集索引包含的列。

通过在非聚集索引中包含非键列,可以创建覆盖更多查询的非聚集索引,这就叫做索引覆盖。

注意,当索引包含查询引用的所有列时,这样的查询通常称为覆盖查询。

首先,从sales.customers表中删除email列上的非聚集索引ix_cust_email

DROP INDEX ix_cust_email
ON sales.customers;

然后,在email列上创建一个新索引ix_cust_email_inc,并额外包括两列first_namelast_name

CREATE UNIQUE INDEX ix_cust_email_inc
ON sales.customers(email)
INCLUDE(first_name,last_name);

现在,查询优化器将只使用非聚集索引来返回查询的请求数据:

包含列的索引可以大大提高查询性能,因为查询中的所有列都包含在索引中;查询优化器可以定位索引中的所有列值,而无需访问表或聚集索引,从而减少磁盘I/O操作。

键列存储在索引的所有级别中,而非键列仅存储在叶级别中。

注意:键列存储在索引的所有级别中,而非键列仅存储在叶级别中。

创建包含列的索引的语法

CREATE [UNIQUE] INDEX index_name
ON table_name(key_column_list)
INCLUDE(included_column_list);
posted @   平元兄  阅读(223)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek “源神”启动!「GitHub 热点速览」
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示