当前位置: 首页 > article >正文

SQL Server 中的覆盖索引

1. 覆盖索引的工作原理

当查询只涉及索引中已经包含的列时,SQL Server 可以直接使用索引来返回查询结果,而不需要回表到数据页去检索实际的数据行。覆盖索引因此能够显著减少 I/O 操作,提高查询效率。

例如,假设有一个表 Employees,包含以下列:

CREATE TABLE Employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    age INT,
    salary DECIMAL(10, 2)
);

如果你为 namesalary 列创建了一个复合索引:

CREATE INDEX idx_name_salary ON Employees(name, salary);

那么在以下查询中,SQL Server 将使用该覆盖索引:

SELECT name, salary FROM Employees WHERE name = 'John Doe';

因为查询只涉及 namesalary,SQL Server 可以直接从索引中获取结果,而不需要访问表中的数据行。

2. 覆盖索引的创建

为了优化查询性能,SQL Server 提供了包括列(INCLUDE)的功能,允许你在索引中包含额外的列,这些列不会作为索引的排序依据,但会存储在索引叶子节点中,供查询时直接使用。

例如,假设你经常执行如下查询:

SELECT name, salary, age FROM Employees WHERE salary > 50000;

你可以创建一个索引,其中包括 namesalary 作为索引的排序列,并将 age 列作为“包括列”:

CREATE INDEX idx_salary_name IN Employees(salary, name)
INCLUDE (age);

此时,salaryname 列作为排序列,age 列作为包括列,这样 SQL Server 在执行查询时就能直接从索引中获取所有所需的列,避免了回表操作。

3. SQL Server 的覆盖索引优势
  • 性能提升:避免回表,减少磁盘 I/O,查询结果可以直接从索引中返回,性能得到提升。
  • 存储优化:合理使用 INCLUDE 子句,可以避免将所有查询字段都作为排序列,从而减少索引的大小。
4. 使用 INCLUDE 子句

在 SQL Server 中,INCLUDE 子句是优化覆盖索引的重要工具。它允许你在索引中包含额外的列,而不会影响索引的排序方式,且这些列仅用于覆盖查询。

例如,以下索引创建语句:

CREATE INDEX idx_name_salary INCLUDE (age);

该索引会包括 namesalary 作为排序列,并且在索引的叶子节点中包含 age 列。当查询涉及 namesalaryage 时,SQL Server 会使用此索引覆盖查询,而不需要访问数据表。

5. 注意事项
  • 索引大小:覆盖索引的大小可能会变得较大,尤其是当你包含多个列或大列时,因此要小心选择需要覆盖的列。
  • 更新开销:如果索引涉及频繁更新的列,维护覆盖索引的开销可能会增加。
6. 例子总结

假设你有一个查询:

SELECT name, salary FROM Employees WHERE salary > 50000;

如果你创建如下的索引:

CREATE INDEX idx_salary_name ON Employees(salary, name);

那么这个查询将完全由覆盖索引处理,SQL Server 不需要回表。假如查询涉及更多列,例如:

SELECT name, salary, age FROM Employees WHERE salary > 50000;

那么你可以创建一个包含 age 列的索引:

CREATE INDEX idx_salary_name_age ON Employees(salary, name) INCLUDE (age);

在这种情况下,SQL Server 会使用该索引覆盖查询,不需要回表到 Employees 表来查找 age 列的数据。

总结

SQL Server 中的覆盖索引与其他数据库系统的概念非常相似,都是通过索引中包含查询所需的所有列来避免回表,从而提升查询性能。SQL Server 通过 INCLUDE 子句提供了更大的灵活性,使得覆盖索引的创建可以更加精细和高效。

创建覆盖索引的脚本与普通索引脚本是类似的,但有一个关键的区别:在创建覆盖索引时,通常会使用 INCLUDE 子句来指定额外的列,使索引包含查询所需的所有字段,而不影响索引的排序列。

1. 普通索引创建脚本

普通索引创建脚本通常只指定索引的排序列。例如:

CREATE INDEX idx_name_salary ON Employees(name, salary);

这个索引 idx_name_salary 是一个普通的非覆盖索引,它按 namesalary 列排序。如果查询只涉及 namesalary,这个索引就能加速查询。但如果查询还需要其他列(比如 age),SQL Server 仍然需要回表去查找这些列的数据。

2. 覆盖索引创建脚本

覆盖索引的创建脚本除了指定排序列外,还会使用 INCLUDE 子句将额外的列包含在索引的叶子节点中,这样可以避免回表。例如,如果你希望查询涉及 namesalaryage,你可以创建一个覆盖索引,包含所有需要的列:

CREATE INDEX idx_name_salary_age ON Employees(name, salary)
INCLUDE (age);

在这个例子中:

  • name 和 salary 是排序列,它们决定了索引的组织方式。
  • age 列是通过 INCLUDE 子句包含在索引中的,它不会影响索引的排序方式,但是查询中需要 age 时,SQL Server 会直接从索引中获取它,而无需回表去查找实际的数据。

3. 总结区别

  • 普通索引:只有排序列,没有使用 INCLUDE 子句,适用于仅查询排序列的情况。
  • 覆盖索引:使用 INCLUDE 子句将额外的列包含在索引中,适用于查询包含多个列时,避免回表。

示例比较

  • 普通索引
CREATE INDEX idx_name_salary ON Employees(name, salary);
  • 覆盖索引
CREATE INDEX idx_name_salary_age ON Employees(name, salary)
INCLUDE (age);

关键点

  • INCLUDE 子句只是用来将非排序列(查询需要的列)包括进索引叶子节点,以提高查询性能。
  • 在大多数情况下,只有当查询涉及多个列时,才使用覆盖索引。如果查询只涉及少数几列,使用普通索引可能更合适。

这样,覆盖索引的创建脚本和普通索引脚本的区别就是是否使用了 INCLUDE 子句。


http://www.kler.cn/a/471975.html

相关文章:

  • 生物医学信号处理--绪论
  • Ubuntu 下载安装 elasticsearch7.17.9
  • 一、金融知识储备
  • [Linux]Mysql9.0.1服务端脱机安装配置教程(redhat)
  • Elixir语言的语法糖
  • Pycharm连接远程解释器
  • 单片机实物成品-010 智能宠物喂食系统(代码+硬件+论文)
  • C++二十三种设计模式之单例模式
  • 小白学Pytorch
  • Java到底是值传递还是引用传递????
  • 无人机低小慢探测难题!
  • 分布式专题(11)之Zookeeper特性与节点数据类型详解
  • Understanding the Lomb–Scargle Periodogram
  • Sphinx 使用指南
  • Eclipse配置Tomcat服务器(最全图文详解)
  • 智能工厂的设计软件 应用场景的一个例子: 为AI聊天工具添加一个知识系统 之25 祖传代码:垂类划分出负责监管控的“三层结构”
  • ArmSoM RK3588/RK3576核心板,开发板网络设置
  • 《Windows基础与网络安全:用户账户管理与安全策略》
  • c#集成npoi根据excel模板导出excel
  • TCP 演进之路:软硬件跷跷板与新征程