🙏 感谢您的支持! 我们在七月份已经筹集了 $65 — 这足够我们工作到下个月。请帮助我们保持进度,进一步支持这个项目。 支持这个项目 →
SQL 代码已复制到剪贴板

课程 10.5 · 阅读时间:~10 分钟

本课程介绍 SQL 索引及其在查询性能中的作用。您将学习索引是什么,它如何帮助更快地检索数据,以及为什么有时它会减慢数据修改操作。我们将通过使用 Sakila 表创建和验证索引的基本示例进行讲解。到本课程结束时,您将能够更有意识地使用索引来加速实际查询。

介绍 SQL 索引

在上一课中,我们学习了如何使用 EXPLAIN 阅读执行计划并检测瓶颈。下一个逻辑步骤是理解用于加速查找的核心机制:索引。

索引与 DBMS 搜索行的方式直接相关。如果没有索引,服务器通常会扫描整个表。使用合适的索引,它可以更快地跳转到相关数据。

介绍 SQL 索引及其如何影响查询性能


索引是什么

SQL 索引是一个额外的数据结构,帮助 DBMS 通过列值更快地找到行。

一个简单的类比是书籍索引。您不需要阅读每一页,而是使用索引直接跳转到相关部分。

在关系数据库中,B-tree 索引是常用的,并且适用于:

  • 精确查找 (=);
  • 范围 (>, <, BETWEEN);
  • 在索引列上排序 (ORDER BY)。

索引如何影响性能

它们加速读取 (SELECT)

WHERE 条件使用索引列时,DBMS 可以在不扫描整个表的情况下定位行。

它们可能减慢写入 (INSERT, UPDATE, DELETE)

每个索引必须保持最新。当数据发生变化时,DBMS 会同时更新表和相关索引。

它们需要额外的存储

索引是单独存储的,并消耗磁盘空间。在每一列上创建索引通常是一个不好的策略。


基本语法

创建单列索引:

CREATE INDEX idx_customer_last_name
ON customer (last_name);

删除索引(语法因 DBMS 而异):

DROP INDEX idx_customer_last_name ON customer;

注意:在 PostgreSQL 中,形式为 DROP INDEX index_name;,不带表名。


示例 1:加速对一列的过滤

假设我们经常按姓氏搜索客户:

SELECT
   customer_id,
   first_name,
   last_name
FROM customer
WHERE last_name = 'SMITH';

如果没有 last_name 的索引,DBMS 可能会对 customer 进行完全扫描。创建索引后,查找通常会变为更高效的访问类型。

使用 EXPLAIN 验证:

EXPLAIN
SELECT
   customer_id,
   first_name,
   last_name
FROM customer
WHERE last_name = 'SMITH';

结果:在执行计划中,您应该看到索引使用情况(在 MySQL 中为 key/possible_keys,在 PostgreSQL 中为 Index Scan)。


示例 2:复合索引

如果查询经常按两个字段一起过滤,复合索引是有用的。

CREATE INDEX idx_payment_customer_date
ON payment (customer_id, payment_date);

一个适合此索引的查询:

SELECT
   payment_id,
   customer_id,
   amount,
   payment_date
FROM payment
WHERE customer_id = 15
  AND payment_date >= '2005-07-01'
ORDER BY payment_date;

注意:复合索引中的列顺序很重要。在许多情况下,将更频繁过滤的字段放在前面。


何时可能不使用索引

即使存在索引,优化器也可能会跳过它。常见原因:

  • WHERE 中对索引列使用函数 (YEAR(payment_date));
  • % 开头的模式搜索 (LIKE '%abc');
  • 列选择性非常低;
  • 复合索引中的列顺序不合适。

一个常常阻止索引使用的条件示例:

SELECT
   payment_id,
   payment_date
FROM payment
WHERE YEAR(payment_date) = 2005;

一个更适合索引的版本:

SELECT
   payment_id,
   payment_date
FROM payment
WHERE payment_date >= '2005-01-01'
  AND payment_date < '2006-01-01';

实用建议

  • 为真正频繁的查询添加索引,而不是“以防万一”。
  • 从用于 WHEREJOINORDER BY 的列开始。
  • 添加索引后,使用 EXPLAIN 比较执行计划。
  • 保持平衡:索引过多可能会影响写入性能。

本课的关键要点:

  • 索引是加速行查找的结构。
  • 索引通常提高 SELECT 性能,但可能减慢 INSERTUPDATEDELETE
  • 单列和复合索引解决不同的过滤模式。
  • 复合索引中的列顺序至关重要。
  • EXPLAIN 有助于验证 DBMS 是否使用您的索引。

面试问题

什么是 SQL 索引,它有什么用?

索引是一个额外的数据结构,通过列值加速行查找。它有用,因为它减少了读取时间和扫描的数据量。

为什么索引可以加速 SELECT 但减慢 INSERT

对于读取,索引有助于更快地定位行。对于写入,DBMS 必须同时更新表数据和索引结构,这增加了工作量。

如何验证索引是否实际被使用?

运行 EXPLAIN 以查看查询并检查执行计划:访问类型、选择的索引和估计的行数。

在下一课中,我们将介绍日常工作中使用的错误处理和 SQL 调试技术。

尝试解决以下任务,以巩固您在本课中学到的内容。

  1. SQL中的索引是什么?
  2. 创建索引
  3. 创建唯一索引