SQL Server 中的覆盖索引

embedded/2025/1/11 12:45:29/
1. 覆盖索引的工作原理

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

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

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

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

sql">CREATE INDEX idx_name_salary ON Employees(name, salary);

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

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

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

2. 覆盖索引的创建

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

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

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

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

sql">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 子句是优化覆盖索引的重要工具。它允许你在索引中包含额外的列,而不会影响索引的排序方式,且这些列仅用于覆盖查询。

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

sql">CREATE INDEX idx_name_salary INCLUDE (age);

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

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

假设你有一个查询:

sql">SELECT name, salary FROM Employees WHERE salary > 50000;

如果你创建如下的索引:

sql">CREATE INDEX idx_salary_name ON Employees(salary, name);

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

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

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

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

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

总结

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

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

1. 普通索引创建脚本

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

sql">CREATE INDEX idx_name_salary ON Employees(name, salary);

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

2. 覆盖索引创建脚本

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

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

在这个例子中:

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

3. 总结区别

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

示例比较

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

关键点

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

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


http://www.ppmy.cn/embedded/153007.html

相关文章

相机和激光雷达的外参标定 - 无标定板版本

1. 实现的效果 通过本软件实现求解相机和LiDAR的外参,即2个传感器之间的三维平移[x, y, z]和三维旋转[roll, pitch, yaw]。完成标定后,可将点云投影到图像,效果图如下: 本软件的优势:(1)无需特…

spring task使用

Spring Task 简介 Spring Task 是 Spring 框架原生自带的任务调度框架,它犹如一把瑞士军刀,为开发者提供了丰富多样的功能,助力轻松创建和管理定时任务。相较于其他一些第三方任务调度框架,Spring Task 最大的优势在于其与 Sprin…

大语言模型训练的数据集从哪里来?

继续上篇文章的内容说说大语言模型预训练的数据集从哪里来以及为什么互联网上的数据已经被耗尽这个说法并不专业,再谈谈大语言模型预训练数据集的优化思路。 1. GPT2使用的数据集是WebText,该数据集大概40GB,由OpenAI创建,主要内…

ffmpeg-avio实战:打开本地文件或者网络直播流dome

使用ffmpeg打开打开本地文件或者网络直播流的一个小dome。流程产靠ffmpeg4.x系列的解码流程-CSDN博客 #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavformat/avio.h> #include <libavutil/file.h> #include &l…

算能AI计算服务器SE5设备树的二次修改实操

目录 1.大纲 2.实操 2.下载对应文件包 3.解包启动文件 4.修改对应的设备树 5.重启后 教程链接&#xff1a;https://github.com/sophgo/sophon-tools/tree/main/source/pmemory_edit 1.大纲 2.实操 2.1 选择串口&#xff0c;波特率115200&#xff0c;重启设备&#xff0…

MDX语言的网络编程

MDX语言的网络编程 引言 MDX&#xff08;Multidimensional Expressions&#xff09;是一种多维表达式语言&#xff0c;广泛应用于数据分析和数据挖掘环境中。虽然MDX的主要目的是进行多维数据的查询和分析&#xff0c;但它在网络编程中也有其独特的应用场景。本文将探讨MDX在…

Redis 三大问题:缓存穿透、缓存击穿、缓存雪崩

Redis 作为高性能的内存数据库&#xff0c;广泛应用于缓存场景。然而&#xff0c;在实际使用中&#xff0c;可能会遇到三大经典问题&#xff1a;缓存穿透、缓存击穿 和 缓存雪崩。这些问题如果不加以解决&#xff0c;可能会导致系统性能下降甚至崩溃。 1. 缓存穿透 问题描述 …

利用Java爬取1688商品详情API接口:技术与应用指南

引言 1688作为中国领先的B2B电子商务平台&#xff0c;拥有海量的商品信息。对于商家和市场研究人员来说&#xff0c;能够从1688获取商品详情信息&#xff0c;对于市场分析、竞品研究等具有重要价值。本文将详细介绍如何使用Java编写爬虫程序&#xff0c;以合法、高效的方式获取…