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

MySQL EXPLAIN 中的七种 type 类型详解

深入理解 MySQL EXPLAIN 的七种 type 类型

掌握 MySQL 的 EXPLAIN 命令是数据库性能优化的必备技能,而其中的 type 字段更是分析查询性能的关键指标。本文将带你深入理解七种 type 类型的含义、使用场景和优化策略。

一、什么是 EXPLAIN 的 type 字段?

在 MySQL 中,EXPLAIN 命令用于分析 SQL 查询的执行计划。其中的 type 字段表示 MySQL 决定如何查找表中的行,它直接反映了查询的性能特征。理解不同类型的访问方式,对于 SQL 优化至关重要。

二、七种 type 类型详解

1. system ★★★★★(最优)

特点

  • 表只有一行数据(系统表)
  • 是 const 类型的特例,性能最佳

示例场景

-- 查询系统表中的单行数据
EXPLAIN SELECT * FROM mysql.proxies_priv WHERE user = 'root';

输出特征

  • type: system
  • rows: 1

优化建议:这已经是最高效的访问方式,无需进一步优化。

2. const ★★★★★

特点

  • 通过主键或唯一索引的等值查询
  • 最多返回一条记录
  • 查询条件必须是常量值

示例场景

-- 主键等值查询
EXPLAIN SELECT * FROM users WHERE id = 1;-- 唯一索引等值查询
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';

输出特征

  • type: const
  • rows: 1
  • key: 使用的索引名

优化建议:确保查询使用主键或唯一索引,这是理想的查询方式。

3. eq_ref ★★★★☆

特点

  • 多表连接时,使用主键或唯一索引作为关联条件
  • 对于前表的每一行,后表只返回一条匹配记录
  • 通常出现在高性能的 JOIN 操作中

示例场景

-- orders.user_id 是 users.id 的外键,且 users.id 是主键
EXPLAIN SELECT * FROM orders JOIN users ON orders.user_id = users.id;

输出特征

  • type: eq_ref
  • key: 使用的索引名
  • 通常与 constref 一起出现在 JOIN 查询中

优化建议:确保连接条件使用主键或唯一索引,检查外键关系是否正确建立。

4. ref ★★★☆☆

特点

  • 使用普通索引的等值查询
  • 可能返回多行记录
  • 性能优于全表扫描,但不如 const 和 eq_ref

示例场景

-- name 列有普通索引
EXPLAIN SELECT * FROM users WHERE name = '张三';

输出特征

  • type: ref
  • key: 使用的索引名
  • rows: 预计扫描行数

优化建议

  • 为频繁查询的条件添加合适的索引
  • 考虑使用覆盖索引减少回表操作
  • 注意索引的选择性,高选择性列更适合建索引

5. range ★★☆☆☆

特点

  • 使用索引进行范围扫描
  • 常见于 BETWEEN、>、<、IN 等范围操作
  • 只检索给定范围内的行

示例场景

-- age 列有索引
EXPLAIN SELECT * FROM users WHERE age BETWEEN 20 AND 30;
EXPLAIN SELECT * FROM users WHERE id IN (1, 2, 3);

输出特征

  • type: range
  • key: 使用的索引名
  • rows: 范围扫描的行数估计

优化建议

  • 注意范围查询后的列索引会失效
  • 在联合索引中,将范围查询列放在最后
  • 考虑使用覆盖索引优化查询

6. index ★★☆☆☆

特点

  • 全索引扫描(比全表扫描好)
  • 只扫描索引树,不扫描数据行
  • 常见于覆盖索引查询或需要索引排序的场景

示例场景

-- 索引覆盖查询(status 有索引)
EXPLAIN SELECT status FROM users;-- 使用索引但需要排序
EXPLAIN SELECT id FROM users ORDER BY id;

输出特征

  • type: index
  • key: 使用的索引名
  • Extra: Using index(如果使用覆盖索引)

优化建议

  • 考虑是否真的需要所有索引数据
  • 对于大表,全索引扫描仍然很耗资源
  • 评估是否可以通过添加 LIMIT 限制结果集

7. ALL ☆☆☆☆☆(最差)

特点

  • 全表扫描
  • 性能最差,尤其是大表
  • 表示没有使用任何索引

示例场景

-- 没有为 address 列创建索引
EXPLAIN SELECT * FROM users WHERE address LIKE '%北京%';-- 没有合适的索引可用
EXPLAIN SELECT * FROM users WHERE created_at > '2023-01-01';

输出特征

  • type: ALL
  • key: NULL
  • rows: 表的总行数
  • Extra: Using where

优化建议

  • 必须为查询条件添加合适的索引
  • 考虑使用覆盖索引
  • 限制返回的数据量(添加 LIMIT)
  • 评估是否需要所有列,避免 SELECT *

三、性能对比总结表

type扫描方式性能等级优化状态建议
system系统表一行★★★★★最优保持
const主键/唯一索引等值★★★★★优秀保持
eq_ref连接使用主键★★★★☆很好检查连接条件
ref普通索引等值★★★☆☆良好添加合适索引
range索引范围扫描★★☆☆☆一般注意范围查询
index全索引扫描★★☆☆☆需优化检查覆盖索引
ALL全表扫描☆☆☆☆☆必须优化添加索引

四、实战优化案例

问题查询

EXPLAIN SELECT * FROM orders WHERE customer_id = 100 AND order_date > '2023-01-01';

假设当前 type 显示为 ALL,表示全表扫描。

优化步骤

  1. 添加联合索引

    ALTER TABLE orders ADD INDEX idx_customer_date(customer_id, order_date);
    
  2. 验证优化效果

    EXPLAIN SELECT * FROM orders 
    WHERE customer_id = 100 AND order_date > '2023-01-01';
    

    现在 type 应该变为 range

  3. 进一步优化(使用覆盖索引)

    EXPLAIN SELECT order_id, order_date FROM orders 
    WHERE customer_id = 100 AND order_date > '2023-01-01';
    

    如果只需要部分列,可以考虑使用覆盖索引。

http://www.dtcms.com/a/395421.html

相关文章:

  • NestJS认识
  • 6.MySQL索引的数据结构【面试题】
  • 【vLLM 最新版v0.10.2】docker运行openai服务与GGUF量化使用方式
  • 鸿蒙开发入门:ArkTS基础与实战
  • #C语言——刷题攻略:牛客编程入门训练(十三):一维数组(二),轻松拿捏!
  • 2.16Vue全家桶-Vuex状态管理
  • 【SSR】SSR 性能问题
  • 《UE教程》第二章第四回——父类蓝图
  • GORM库用法查漏补缺
  • C++11 移动语义与右值
  • FPGA学习笔记——图像处理之对比度调节(直方图均衡化)
  • 如何进行人脸识别
  • 计算机视觉笔试选择题:题组1
  • 第八篇:常量表达式:从const到constexpr的革命
  • RV1126 NO.30:RV1126多线程获取音频AI的PCM数据
  • 基于蚁群算法解决车辆路径问题(VRP)的MATLAB实现
  • C语言自学--C语⾔内存函数
  • 磁带记录仪:从磁带到数字的数据存储之旅
  • 【运维】Ubuntu上WebDAV挂载与自动同步完整指南
  • Ubuntu之旅-04 Docker
  • python(73) 引用.dll文件并调用函数
  • Chrome 学习小记5——demo:(动态壁纸基础)
  • 手写 Android Dex VMP 壳:自定义虚拟机 + 指令解释执行全流程
  • 【Netty】创建一个 SSL 处理器,实现客户端与服务器之间的安全通信
  • 13 Python数据结构与算法
  • 爱:宇宙的心跳
  • Python字节数据写入文本文件完全指南:从基础到高级实战
  • 零基础Windows10安装LLVM
  • selenium三种等待方式详解
  • Leetcode总结速记