MySQL的`EXPLAIN`：如何利用其`Extra`列的`Using index condition`与`Using filesort`判断查询优劣？

admin
Sun, 07 Sep 2025 12:15:42 +0000
Mysql, explain, mysql, using

好的，让我们深入探讨MySQL EXPLAIN 命令中 Extra 列的 Using index condition 和 Using filesort，并分析它们如何帮助我们判断查询的优劣。 讲座：MySQL EXPLAIN 中的 Using Index Condition 和 Using Filesort 大家好！今天我们聚焦于 MySQL 查询优化中一个非常重要的工具：EXPLAIN 命令，特别是它的 Extra 列中的两个关键标志：Using index condition 和 Using filesort。理解这两个标志的含义，并掌握它们对查询性能的影响，是优化 MySQL 查询的关键一步。 1. EXPLAIN 命令基础回顾 在深入 Using index condition 和 Using filesort 之前，我们先简单回顾一下 EXPLAIN 命令的作用。 EXPLAIN 命令用于分析 MySQL 如何执行一个 SELECT 语句。它可以帮助我们了解查询的执行计划，包括： id: 查询的标识符，表示查询中执行 select 子句或操作的顺序。 select_type: …

继续阅读“MySQL的`EXPLAIN`：如何利用其`Extra`列的`Using index condition`与`Using filesort`判断查询优劣？”

The post MySQL的`EXPLAIN`：如何利用其`Extra`列的`Using index condition`与`Using filesort`判断查询优劣？ first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

好的，让我们深入探讨MySQL EXPLAIN 命令中 Extra 列的 Using index condition 和 Using filesort，并分析它们如何帮助我们判断查询的优劣。

讲座：MySQL EXPLAIN 中的 Using Index Condition 和 Using Filesort

大家好！今天我们聚焦于 MySQL 查询优化中一个非常重要的工具：EXPLAIN 命令，特别是它的 Extra 列中的两个关键标志：Using index condition 和 Using filesort。理解这两个标志的含义，并掌握它们对查询性能的影响，是优化 MySQL 查询的关键一步。

1. EXPLAIN 命令基础回顾

在深入 Using index condition 和 Using filesort 之前，我们先简单回顾一下 EXPLAIN 命令的作用。 EXPLAIN 命令用于分析 MySQL 如何执行一个 SELECT 语句。它可以帮助我们了解查询的执行计划，包括：

id: 查询的标识符，表示查询中执行 select 子句或操作的顺序。

select_type: 查询的类型，例如 SIMPLE、PRIMARY、SUBQUERY 等。

table: 查询涉及的表。

partitions: 如果表是分区表，则显示查询访问的分区。

type: MySQL 如何查找表中的行，表示访问类型，从最佳到最差的顺序通常是：system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。

possible_keys: MySQL 可能使用的索引。

key: MySQL 实际使用的索引。

key_len: 使用的索引的长度。

ref: 用于索引查找的列或常量。

rows: MySQL 估计需要扫描的行数。

filtered: 过滤掉的行百分比。

Extra: 包含有关 MySQL 如何执行查询的额外信息，我们今天主要关注的是 Using index condition 和 Using filesort。

2. Using Index Condition (索引条件下推 – ICP)

Using index condition (简称 ICP) 是一种优化技术，它允许 MySQL 在索引层过滤数据。如果没有 ICP，存储引擎会把索引中的数据全部返回给 MySQL 服务器，然后由服务器根据 WHERE 子句进行过滤。有了 ICP，MySQL 可以将 WHERE 子句的部分过滤条件下推到存储引擎层，这样存储引擎就可以在索引层直接过滤掉不满足条件的数据，减少了不必要的数据传输和服务器端的 CPU 消耗。

2.1 ICP 的工作原理

假设我们有一个表 employees，包含列 id、name 和 age，并在 name 列上创建了索引。

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    age INT
);

CREATE INDEX idx_name ON employees(name);

INSERT INTO employees (id, name, age) VALUES
(1, 'Alice', 30),
(2, 'Bob', 25),
(3, 'Charlie', 35),
(4, 'David', 28),
(5, 'Alice', 40);

现在，我们执行以下查询：

SELECT * FROM employees WHERE name LIKE 'A%' AND age > 32;

如果没有 ICP，MySQL 会首先使用 idx_name 索引找到所有以 "A" 开头的 name，然后将这些行的所有数据返回给服务器，服务器再过滤掉 age <= 32 的行。

有了 ICP，MySQL 会将 age > 32 这个条件也下推到存储引擎层。存储引擎在读取 idx_name 索引时，会同时检查 age 是否满足条件，只返回满足 name LIKE 'A%' AND age > 32 的行，从而减少了数据传输和服务器端的过滤工作。

2.2 如何判断是否使用了 ICP

我们可以使用 EXPLAIN 命令来判断是否使用了 ICP。

EXPLAIN SELECT * FROM employees WHERE name LIKE 'A%' AND age > 32;

如果 EXPLAIN 输出的 Extra 列包含 Using index condition，则表示使用了 ICP。

2.3 ICP 的适用场景

WHERE 子句中包含可以使用索引的条件，并且还有其他不能使用索引的条件。

索引需要覆盖查询的所有列（覆盖索引）。

2.4 ICP 的优点

减少了存储引擎和 MySQL 服务器之间的数据传输量。

减少了 MySQL 服务器的 CPU 消耗。

提高了查询性能。

2.5 ICP 的限制

ICP 只能用于二级索引（非聚簇索引）。

ICP 的目标是减少读取完整行的次数，所以它通常与读取整行数据的操作结合使用，例如 SELECT *。

3. Using Filesort (文件排序)

Using filesort 表示 MySQL 需要对结果集进行外部排序，也就是无法利用索引来满足 ORDER BY 子句的需求。这意味着 MySQL 需要将数据从磁盘读取到内存，然后在内存中进行排序，或者如果数据量太大，需要在磁盘上进行排序。 Using filesort 通常会严重影响查询性能，因为它是一个耗时的操作。

3.1 filesort 的工作原理

当 MySQL 无法使用索引来满足 ORDER BY 子句时，它会使用 filesort 算法。 filesort 算法有两种主要类型：

Two-Pass Algorithm (两次传递算法): MySQL 首先读取需要排序的列以及 rowid (或 primary key) 到内存缓冲区，然后在内存中对这些列进行排序。 排序后，MySQL 根据 rowid (或 primary key) 再次读取完整的行数据。这种算法需要两次读取数据。

Single-Pass Algorithm (一次传递算法): MySQL 直接读取所有需要的列到内存缓冲区，然后在内存中进行排序。 这种算法只需要一次读取数据，但需要更大的内存空间。

MySQL 会根据可用的内存大小和排序数据的大小来选择使用哪种 filesort 算法。

3.2 如何判断是否使用了 filesort

我们可以使用 EXPLAIN 命令来判断是否使用了 filesort。

EXPLAIN SELECT * FROM employees ORDER BY age;

如果 EXPLAIN 输出的 Extra 列包含 Using filesort，则表示使用了 filesort。

3.3 避免 filesort 的方法

避免 filesort 的最佳方法是创建合适的索引，以便 MySQL 可以使用索引来满足 ORDER BY 子句。

创建覆盖索引: 如果 ORDER BY 子句中的列包含在索引中，并且索引也覆盖了查询的所有列，那么 MySQL 就可以直接从索引中读取数据，而不需要进行 filesort。

使用与 WHERE 子句相同的索引: 如果 WHERE 子句和 ORDER BY 子句都使用相同的列，那么可以创建一个包含这些列的联合索引。

3.4 filesort 的优化

即使无法完全避免 filesort，我们仍然可以通过一些方法来优化它：

增加 sort_buffer_size: sort_buffer_size 是 MySQL 用于排序的内存缓冲区的大小。 增加 sort_buffer_size 可以让 MySQL 在内存中排序更多的数据，从而减少磁盘 I/O。

选择合适的排序算法: MySQL 5.7 之后引入了新的排序算法，可以根据数据量和内存大小自动选择最佳算法。

减少需要排序的数据量: 尽量使用 WHERE 子句过滤掉不需要的数据，减少需要排序的数据量。

4. 案例分析

案例 1: 优化 ORDER BY 子句

假设我们有一个表 orders，包含列 id、customer_id 和 order_date，我们需要按照 order_date 对订单进行排序。

CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    order_date DATE
);

INSERT INTO orders (id, customer_id, order_date) VALUES
(1, 101, '2023-01-15'),
(2, 102, '2023-02-20'),
(3, 101, '2023-03-10'),
(4, 103, '2023-04-05'),
(5, 102, '2023-05-12');

如果执行以下查询：

EXPLAIN SELECT * FROM orders ORDER BY order_date;

EXPLAIN 输出的 Extra 列可能会包含 Using filesort。

为了避免 filesort，我们可以创建一个 order_date 列的索引：

CREATE INDEX idx_order_date ON orders(order_date);

再次执行 EXPLAIN 命令，Extra 列应该不再包含 Using filesort。

案例 2: 优化 WHERE 和 ORDER BY 子句

假设我们需要查询特定客户的订单，并按照 order_date 排序：

EXPLAIN SELECT * FROM orders WHERE customer_id = 101 ORDER BY order_date;

如果 Extra 列包含 Using filesort，我们可以创建一个包含 customer_id 和 order_date 的联合索引：

CREATE INDEX idx_customer_order_date ON orders(customer_id, order_date);

5. 总结：监控Extra，构建合适的索引

Using index condition 和 Using filesort 是 EXPLAIN 命令中非常重要的两个标志。 Using index condition 表示使用了索引条件下推，可以提高查询性能。 Using filesort 表示需要进行外部排序，通常会降低查询性能。 通过理解这两个标志的含义，并采取相应的优化措施，我们可以显著提高 MySQL 查询的性能。 关键在于创建合适的索引，让 MySQL 可以有效地利用索引来过滤数据和排序数据。

希望这次讲座能够帮助大家更好地理解和利用 EXPLAIN 命令，优化 MySQL 查询。 感谢大家的时间！