MySQL索引EXPLAIN执行计划type类型解析

MySQL索引EXPLAIN执行计划type类型解析

在 MySQL 中,使用 EXPLAIN 命令可以查看 SQL 查询的执行计划,其中 type 字段表示 MySQL 在查询时访问表的方式(即连接类型或访问类型)。不同的 type 值反映了查询的效率和扫描范围。本文将详细解析 type 的各种取值、它们的效率排序,以及 typerange 的适用场景。

一、type 的各种类型及效率排序

以下是 EXPLAIN 输出中 type 字段可能出现的取值,从效率最高到最低排序:

  1. system

    • 描述: 表只有一行数据(通常是系统表)。这是最快的访问类型。
    • 效率: 最高,因为只需要读取一行数据。
    • 场景: 常用于 MyISAM 引擎的系统表,InnoDB 很少出现。
  2. const

    • 描述 : 通过主键或唯一索引查找,且最多返回一行数据。查询条件是常量(例如 WHERE id = 5)。
    • 效率 : 极高,仅次于 system,因为直接定位到单行。
    • 场景: 主键查询或唯一索引查询。
  3. eq_ref

    • 描述: 在联表查询中,通过主键或唯一非空索引进行等值匹配,每行只匹配一行数据。
    • 效率: 非常高,逐行精确匹配。
    • 场景 : 例如 SELECT * FROM t1 JOIN t2 ON t1.id = t2.id,其中 t2.id 是主键或唯一索引。
  4. ref

    • 描述: 通过非唯一索引或唯一索引的前缀进行等值匹配,可能返回多行数据。
    • 效率: 中等偏高,依赖索引选择性。
    • 场景 : 例如 WHERE name = 'Alice'name 是普通索引。
  5. range

    • 描述: 通过索引进行范围扫描,返回符合条件的行。
    • 效率: 中等,优于全表扫描但不如等值匹配。
    • 场景 : 范围查询,如 WHERE id > 10 AND id < 20
  6. index

    • 描述: 全索引扫描,扫描整个索引树而不是表数据。
    • 效率: 中等偏低,比全表扫描稍好。
    • 场景 : 查询只需要索引列即可满足,例如 SELECT indexed_col FROM table
  7. ALL

    • 描述: 全表扫描,逐行检查每一行数据。
    • 效率: 最低,性能最差。
    • 场景: 无索引可用或索引未被优化器选择。

效率排序总结

system > const > eq_ref > ref > range > index > ALL

二、typerange 的情况

typerange 时,说明 MySQL 使用了索引进行范围扫描。以下是常见的触发 range 类型的 SQL 查询场景:

1. 范围查询

最典型的情况是使用范围操作符,例如:

  • ><>=<=

  • BETWEEN ... AND ...

  • 示例:

    sql 复制代码
    SELECT * FROM users WHERE age BETWEEN 18 AND 30;
    SELECT * FROM orders WHERE order_date > '2025-01-01';

2. IN 查询(部分情况)

当使用 IN 指定多个离散值时,如果值是连续的或者优化器认为可以转为范围扫描,type 可能为 range

  • 示例:

    sql 复制代码
    SELECT * FROM products WHERE id IN (1, 2, 3, 4, 5);
    • 注意:如果 IN 的值不连续且数量较多,优化器可能退化为 ref 或其他类型。

3. LIKE 前缀匹配(特定情况)

当使用 LIKE 进行前缀匹配且列有索引时,可能触发 range

  • 示例:

    sql 复制代码
    SELECT * FROM employees WHERE name LIKE 'A%';
    • 注意:如果 LIKE 使用通配符开头(如 %abc),则无法使用索引,退化为 ALL

4. 除了范围查询外的其他情况

除了显式的范围查询,某些条件下优化器可能将查询优化为范围扫描:

  • 多列索引的部分范围匹配
    对于复合索引 (col1, col2),如果 WHERE col1 = 10 AND col2 > 5,对 col2 的范围条件会导致 range
  • 排序或分组优化
    如果查询涉及 ORDER BYGROUP BY,且优化器选择索引范围扫描来避免额外排序,可能是 range

示例分析

假设表 users 有索引 idx_ageage 列上:

sql 复制代码
EXPLAIN SELECT * FROM users WHERE age > 20 AND age < 30;

输出:

  • type: range
  • key: idx_age
  • 原因:使用了索引 idx_age 进行范围扫描。

三、总结

  • type 类型效率 :从 systemALL,效率逐步降低。优化 SQL 时,尽量让 type 靠近左侧(如 consteq_ref)。
  • range 的触发条件 :主要由范围查询触发(如 ><BETWEEN),此外 IN 和某些 LIKE 查询也可能导致 range
  • 优化建议 :为查询条件创建合适的索引,避免全表扫描 (ALL),并尽量使用等值匹配而非范围扫描以提升性能。

通过理解 EXPLAINtype,我们可以更好地分析和优化 SQL 查询,提升数据库性能。

相关推荐
苏渡苇3 小时前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
java·后端·spring·spring cloud·springboot·性能监控
tonydf3 小时前
AI驱动历史项目安全审查
后端·ai编程
她的男孩4 小时前
同一个接口,为什么销售只看到自己的订单?我拆了 681 行数据权限拦截器的源码
java·后端·架构
元界metalite4 小时前
SpringBoot接口通用响应对象设计 - 一个 Resp 管理五种责任
后端
对象存储与RustFS4 小时前
把 RustFS 跑在 Kubernetes 上:官方 Helm Chart 从单机到分布式
后端·rust·开源
SimonKing4 小时前
将cURL 命令直接变成 Java 代码?用JQuick-Curl搞起来
java·后端·程序员
大牧师4 小时前
Nest.js 微服务入门教程
开发语言·javascript·后端·微服务·node.js·nest.js·nest
凤山老林4 小时前
企业级文件服务中台:Spring Boot 集成 MinIO 实现分片存储、生命周期管理与多租户隔离
java·spring boot·后端·minio·文件服务
IT_陈寒4 小时前
Redis的订阅丢失消息?你可能忘了这个配置
前端·人工智能·后端
好好沉淀5 小时前
巧用 Set 去重与复合键:高效统计分组内不重复元素的数量
java·spring boot·后端