Explain参数太多记不住?理解性记忆来帮你!

149 阅读4分钟

你可以这样考虑! 不走索引肯定慢,所以ALL是最低级的。走非唯一索引得分三种情况,走完全部索引就是index,因为走完了,所以也慢。 Range是对索引列范围查询,只走了部分索引,所以会快一些。Ref是对索引列做等值查询,比Range还快。而Eq_Ref是走唯一索引的关联查询,因为关联所以有一些开销,但是因为是唯一,所以比Ref快,而Const是唯一索引做等值查询,而且还不关联,那就更快了。所以就速度来说:All<Index<Range<Ref<Eq_Ref<Const

一、type(访问类型)——数据查找方式

核心口诀
"ALL 全扫,index 全索,range 范围,ref 索引查,eq_ref 唯一连,const 主键到"

1. ALL

  • 场景:全表扫描(性能最差)。
  • 出现条件:无索引或无法使用索引时。
  • 例子SELECT * FROM users WHERE name = 'Alice'name 无索引)。

2. index

  • 场景:全索引扫描(比 ALL 快,但需遍历整个索引树)。
  • 出现条件:需要读取索引的全部数据(如覆盖索引)。
  • 例子SELECT id FROM usersid 是主键索引)。

3. range

  • 场景:索引范围扫描。
  • 出现条件:使用 BETWEENIN>< 等范围查询。
  • 例子SELECT * FROM users WHERE age > 20age 有索引)。

4. ref

  • 场景:普通索引查找(可能返回多行)。
  • 出现条件:使用非唯一索引的等值查询。
  • 例子SELECT * FROM users WHERE email = 'alice@example.com'email 是普通索引)。

5. eq_ref

  • 场景:唯一索引关联(每行最多匹配一条记录)。
  • 出现条件:主键或唯一索引的关联查询(如 JOIN)。
  • 例子SELECT * FROM users JOIN orders ON users.id = orders.user_idorders.user_id 是唯一索引)。

6. const

  • 场景:常量查询(性能最好)。
  • 出现条件:通过主键或唯一索引直接定位单行。
  • 例子SELECT * FROM users WHERE id = 1id 是主键)。

二、select_type(查询类型)——SQL 语句结构

核心口诀
"SIMPLE 简单无子查,PRIMARY 外层顶呱呱,SUBQUERY WHERE 里,DERIVED FROM 子查它"

1. SIMPLE

  • 场景:简单查询(无子查询或 UNION)。
  • 例子SELECT * FROM users WHERE id = 1

2. PRIMARY

  • 场景:最外层的查询(复杂查询中的主查询)。
  • 例子SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)

3. SUBQUERY

  • 场景:子查询位于 WHERE 子句中。
  • 例子SELECT * FROM users WHERE id = (SELECT user_id FROM orders LIMIT 1)

4. DERIVED

  • 场景:子查询位于 FROM 子句(生成临时表)。
  • 例子SELECT * FROM (SELECT * FROM users) AS tmp

5. UNION

  • 场景:UNION 中的第二个或后续查询。
  • 例子SELECT * FROM users UNION SELECT * FROM admins

6. UNION RESULT

  • 场景:UNION 的结果集。
  • 例子:同上 UNION 查询的结果。

三、Extra(附加信息)——执行细节

核心口诀
"Using where 过滤行,Using index 覆盖爽,Using temporary 临时表,Using filesort 排序忙"

1. Using where

  • 场景:需要从存储引擎读取数据后,在 Server 层进行过滤。
  • 例子SELECT * FROM users WHERE age > 20age 无索引)。

2. Using index

  • 场景:覆盖索引(直接从索引获取数据,无需回表)。
  • 例子SELECT id FROM usersid 是主键)。

3. Using temporary

  • 场景:需要临时表处理查询(如 GROUP BYDISTINCT)。
  • 例子SELECT DISTINCT name FROM usersname 无索引)。

4. Using filesort

  • 场景:需要额外排序(可能用到磁盘或内存)。
  • 例子SELECT * FROM users ORDER BY namename 无索引)。

5. Using join buffer

  • 场景:关联查询时使用连接缓冲区(如未走索引的 JOIN)。
  • 例子SELECT * FROM users JOIN orders ON users.name = orders.productnameproduct 无索引)。

四、记忆技巧总结

  1. 关联性能

    • type 的值按性能排序:const > eq_ref > ref > range > index > ALL
    • ExtraUsing index 是好的,Using temporaryUsing filesort 是警告信号。
  2. 场景联想

    • type=ALL 想象成翻遍整个抽屉找东西,type=const 像直接打开抽屉的某个格子。
  3. 对比记忆

    • ref vs eq_refref 是普通索引查多行,eq_ref 是唯一索引查单行。
    • SUBQUERY vs DERIVEDSUBQUERYWHERE 里,DERIVEDFROM 里。

五、实战验证表

字段关键值常见场景性能影响
typeconst主键或唯一索引的等值查询⭐⭐⭐⭐⭐
eq_ref主键关联查询(如 JOIN)⭐⭐⭐⭐
ref普通索引的等值查询⭐⭐⭐
range索引范围查询(如 BETWEEN⭐⭐
index全索引扫描
ALL全表扫描🚨
ExtraUsing index覆盖索引
Using whereServer 层过滤数据⚠️
Using filesort额外排序🚨
Using temporary使用临时表🚨

通过结合口诀和场景,反复分析实际 EXPLAIN 结果,可以逐步内化这些概念!