查询优化的官方文档在 这里

EXPLAIN 的输出格式 译文

1. MySQL 架构

1.1 MySQL 的简化架构

MySQL 可以简单的分为三层:连接层、服务层、存储引擎层。其中服务层包含了 MySQL 的核心组件:

  1. 用户连接层

  2. ---------------------------------------------------------------------
  3. +------------------+
  4. | MySQL 连接池 |
  5. +------------------+
  6. +------------------+-------------+----------+------------------+
  7. | Cache && Buffer | Optimizer | Parser | SQL Interface |
  8. +------------------+-------------+----------+------------------+
  9. ---------------------------------------------------------------------

  10. InnoDB MyISAM Memory Archive Cluster
  11. 存储引擎层

各个组件概述如下:

  • 连接池:维护用于用户连接的线程池,避免频繁创建销毁线程导致的开销。
  • 存储引擎层:提供标准接口,满足这个接口的存储引擎都可以用于 MySQL。
  • SQL Interface:SQL 接口层,接受 SQL 语句并返回结果
  • Parser:解析器,解析和验证 SQL 语句。
  • Cache && Buffer:缓存,由一系列小缓存组成,比如表缓存、记录缓存、key 缓存、权限缓存等。查询命中缓存时,会直接返回缓存中的数据。
  • Optimizer:优化器,执行 SQL 语句之前会进行优化

1.2 工作流程

到 MySQL 的连接建立后,执行的每一条 SQL 语句的流程如下:

  • 调用 SQL Interface,发生 SQL 语句
  • 通过 Parser 解析 SQL 语句,如果发生错误则报错并退出
  • 查询缓存。如果在缓存中发现相同的指令,则命中缓存,数据从缓存返回,不再执行后续步骤
  • 通过 Optimizer 优化 SQL 语句,最终执行的 SQL 语句可能与你发送的 SQL 语句不一样
  • 执行 SQL 语句,结果写入缓存并返回

2. EXPLAIN 概述

EXPLAIN 可以提供 MySQL 语句的执行信息

  • 可以用于 SELECT、DELETE、INSERT、REPLACE 和 UPDATE 五条语句。
  • 显示的信息来自 Optimizer 优化器。

EXPLAIN 命令输出如下:

  1. mysql> EXPLAIN SELECT * FROM people;
  2. +----+-------------+--------+------+---------------+------+---------+------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+--------+------+---------------+------+---------+------+------+-------+
  5. | 1 | SIMPLE | people | ALL | NULL | NULL | NULL | NULL | 9 | |
  6. +----+-------------+--------+------+---------------+------+---------+------+------+-------+
  7. 1 row in set (0.00 sec)
Column JSON Name 说明
id select_id SELECT 标识符
select_type None SELECT 类型
table table_name 输出行对应的表
partitions partitions 匹配的分区
type access_type 连接类型
possible_keys possible_keys 可供选择的索引
key key 实际使用的索引
key_len key_length 实际使用的索引的长度
ref ref 与索引进行比较的列,也就是关联表使用的列
rows rows 要被检查的行数(估算值)
filtered filtered 被表条件过滤的行数的百分比
Extra None 附加信息

id

SELECT 标识符,该值为 SELECT 在查询中的顺序号,如果当前行引用的是其他行的联合查询结果,该值将被设置为 NULL。在这种情况下,表中的列将显示一个类似于

  1. mysql> EXPLAIN SELECT * FROM (SELECT * FROM test) as a;
  2. +----+-------------+------------+------+---------------+------+---------+------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+------------+------+---------------+------+---------+------+------+-------+
  5. | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 3 | |
  6. | 2 | DERIVED | test | ALL | NULL | NULL | NULL | NULL | 3 | |
  7. +----+-------------+------------+------+---------------+------+---------+------+------+-------+
  8. 2 rows in set (0.00 sec)

select_type

SELECT 的类型,可用类型参考下表。如果该值为 SIMPLE 或者 PRIMARY,一个 JSON 格式的 EXPLAIN 将以一个 query_block 的属性显示 SELECT 的类型。

如果查询有任何复杂的子查询,则最外层标记为 PRIMARY,内层可以是 DERIVED、UNION、UNION RESUlT。

select_type Value JSON Name 说明
SIMPLE None 简单的 SELECT (没有使用 UNION 和子查询)
PRIMARY None 使用 UNION 联合查询和子查询时,最外层的 SELECT
UNION None 在 UNION 查询中的第二个或者之后的 SELECT 语句,如果是 UNION 位于 FROM 中则标记为 DERIVED
DEPENDENT UNION dependent (true) 在 UNION 查询中的第二个或者之后的 SELECT 语句,依赖外层的查询
UNION RESULT union_result 联合查询的结果
SUBQUERY None 在子查询中的第一个 SELECT
DEPENDENT SUBQUERY dependent (true) 在 subquery 子查询中的第一个 SELECT,依赖于外层查询
DERIVED None 派生表 SELECT(由 FROM 中的 subquery 子查询引起的临时表)
MATERIALIZED materialized_from_subquery 物化子查询
UNCACHEABLE SUBQUERY cacheable (false) 子查询的结果不能被缓存,必须重新评估外部查询的每一行
UNCACHEABLE UNION cacheable (false) 在 UNION 联合查询中的第二个或者之后的多个 SELECT 都不可缓存的子查询

依赖通常意味着使用了相关子查询。

子查询的分类及评估:

  • 相关子查询:只重新评估一次外部上下文环境的每一组变量的不同值
  • 不可缓存的子查询:重新评估外部上下文环境的每一行数据。

子查询的缓存不同与 query cache 中查询结果的缓存:

  • 子查询缓存:发生在查询执行期间
  • query cache:用来存储查询执行完成后的结果。

table

输出的行引用了哪个表,除了真实表名外,还有临时表的表名。临时表没有任何索引。临时表的表名可以是下列值之一:

  • <union M,N>:有 UNION RESULT 的时候,表名是这个形式。该行指的是 ID 值为 M 和 N 的行的联合。
  • <derivedN>:FROM 中有 SUBQUERY 子查询的时候,表名是这个形式。N 指向子查询对应的行。
  • <subqueryN>:该行指的是一个物化子查询的结果,该结果为 ID 值为 N 的行。

type

数据访问/读取操作的类型,可用值有:ALL、index、range、ref、eq_ref、const/system、NULL。

这是重要指标,type 的结果值从好到坏依次是:

  1. system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

查询至少要达到 range 级别,最好能达到 ref。

All

全表扫描(速度慢,磁盘 I/O 高)。可以增加索引来避免全表扫描

对于非索引字段,查询时触发全表扫描(尽量避免):

  1. mysql> EXPLAIN SELECT * FROM test WHERE value="t2";
  2. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  5. | 1 | SIMPLE | test | ALL | NULL | NULL | NULL | NULL | 3 | Using where |
  6. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  7. 1 row in set (0.00 sec)

index

覆盖索引,所需数据可以直接从索引中获取。与 All 全表扫描类似,但是只扫描索引,所以速度较快。当查询的几个字段刚好都在同一个索引中时,会使用使用覆盖索引,Extra 列对应 Using index。

查询字段被索引包含及超出索引的区别:

  1. mysql> EXPLAIN SELECT value FROM test WHERE value IS NOT NULL;
  2. +----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
  5. | 1 | SIMPLE | test | index | value | value | 43 | NULL | 4 | Using where; Using index |
  6. +----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
  7. 1 row in set (0.00 sec)
  8. mysql> EXPLAIN SELECT * FROM test WHERE value IS NOT NULL;
  9. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  10. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  11. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  12. | 1 | SIMPLE | test | ALL | value | NULL | NULL | NULL | 4 | Using where |
  13. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  14. 1 row in set (0.00 sec)

range

部分索引扫描。key 列显示使用的索引。当指定了索引且对索引使用 =、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN ANDIN (a, b)范围限定操作符时,会使用 range。

对于主键 id 使用范围限定操作符,只读取 id 字段时,触发 range 部分索引扫描:

  1. mysql> EXPLAIN SELECT * FROM test WHERE id BETWEEN 0 AND 2;
  2. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  5. | 1 | SIMPLE | test | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where |
  6. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  7. 1 row in set (0.02 sec)

对于主键 id 使用范围限定操作符,读取索引之外的字段时,触发 range 部分索引扫描。如果只读取索引之内的字段,则触发 index 覆盖索引:

  1. mysql> EXPLAIN SELECT * FROM test WHERE id BETWEEN 0 AND 2;
  2. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  5. | 1 | SIMPLE | test | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where |
  6. +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
  7. 1 row in set (0.00 sec)
  8. mysql> EXPLAIN SELECT id FROM test WHERE id BETWEEN 0 AND 2;
  9. +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
  10. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  11. +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
  12. | 1 | SIMPLE | test | index | PRIMARY | PRIMARY | 4 | NULL | 4 | Using where; Using index |
  13. +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
  14. 1 row in set (0.00 sec)

ref

通过索引访问数据。只有当使用非唯一性索引(PRIMARY 和 UNIQUE 之外的索引)或唯一性索引的非唯一性前缀时才会发生。

这个类型跟 eq_ref 不同的是,它用在关联操作只使用了索引的最左前缀,或者索引不是 UNIQUE 和 PRIMARY KEY。ref 可以用于使用 = 或 <=> 操作符的带索引的列。对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。ref可以用于使用=或<=>操作符的带索引的列。

将 WHERE 用的字段添加到索引后,触发 ref 索引访问:

  1. mysql> EXPLAIN SELECT * FROM test WHERE value="t2";
  2. +----+-------------+-------+------+---------------+-------+---------+-------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+-------+---------+-------+------+-------------+
  5. | 1 | SIMPLE | test | ref | value | value | 43 | const | 1 | Using where |
  6. +----+-------------+-------+------+---------------+-------+---------+-------+------+-------------+
  7. 1 row in set (0.00 sec)

eq_ref

最多只返回一条符合条件的记录。使用唯一性索引或主键查找时会发生。对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。

const

确定最多只有一行匹配时,MySQL 优化器会在查询开始时将这一行数据读入内存(只读一次),这一行的所有字段值被优化器剩余部分当做常量处理。const 用于用常数值比较 PRIMARY KEY 或 UNIQUE 索引的所有部分时。

对于 PRIMARY KEY 主键或 UNIQUE 索引字段,因为其唯一性,查询效率特别高:

  1. mysql> EXPLAIN SELECT * FROM test WHERE id=1;
  2. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  5. | 1 | SIMPLE | test | const | PRIMARY | PRIMARY | 4 | const | 1 | |
  6. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  7. 1 row in set (0.00 sec)

注意,匹配到 const 表后,不能在这个表上再次进行匹配了:

  1. mysql> EXPLAIN SELECT * FROM test WHERE id=1 and value="t2";
  2. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  5. | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
  6. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  7. 1 row in set (0.00 sec)

system

要匹配的表仅有一行数据。这是 const 连接类型的一种特例,

例如下面的子查询,对于内层查询,通过 PRIMARY KEY 主键返回唯一一条数据,对于外层查询,type 就是 system 类型:

  1. mysql> EXPLAIN SELECT * FROM (SELECT * FROM test WHERE id=1) as a;
  2. +----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
  5. | 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
  6. | 2 | DERIVED | test | const | PRIMARY | PRIMARY | 4 | | 1 | |
  7. +----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
  8. 2 rows in set (0.00 sec)

NULL

mysql 在优化 SQL 语句后,分解的某个查询语句命中缓存或使用临时表,不需要访问数据或索引。

possible_keys

possible_keys 中列出本次查询覆盖的所有索引,这些都可能被 MySQL 选择使用。

如果该列的值是 NULL,说明查询语句没有覆盖到索引列,通常会发生全表扫描。可以检查 WHERE 子句是否引用了包含索引的列。

可能有多个可用索引,但可能 MySQL 一个都不会用:

  1. mysql> EXPLAIN SELECT * FROM test WHERE id=1 OR value="t2";
  2. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  5. | 1 | SIMPLE | test | ALL | PRIMARY,value | NULL | NULL | NULL | 4 | Using where |
  6. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  7. 1 row in set (0.00 sec)

使用 SHOW INDEX FROM tbl_name 查看表中已有的索引:

  1. mysql> SHOW INDEX FROM test;
  2. +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
  3. | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
  4. +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
  5. | test | 0 | PRIMARY | 1 | id | A | 4 | NULL | NULL | | BTREE | | |
  6. | test | 0 | unique | 1 | v_unique | A | NULL | NULL | NULL | YES | BTREE | | |
  7. | test | 1 | value | 1 | value | A | NULL | NULL | NULL | YES | BTREE | | |
  8. +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
  9. 3 rows in set (0.00 sec)

key

MySQL 实际使用的索引。如果 key 值为 NULL,表明 MySQL 没有找到执行高效查询的索引。MySQL 一般会通过 possible_keys 中的某个索引查找行,并将那个索引列在 key 列中;但是也可以使用不包含在 possible_keys 列中的索引。

可以在查询语句中使用 FORCE INDEX、USE INDEX、IGNORE INDEX,强制 MySQL 使用或者忽略 possible_keys 列中的索引。

key_len

MySQL 决定使用的 key 的长度。key_len 值能够使你判定 MySQL 实际使用了 multiple-part key 中的多少个 part。如果 key 列的值为 NULL,则 key_len 列值也为 NULL。在不损失精确性的情况下,长度越短越好。

ref

ref 列显示列或常量,这些列或者常量与 key 列中的索引进行比较,以便从表中选择行。

  1. mysql> EXPLAIN SELECT * FROM test WHERE id=1;
  2. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  5. | 1 | SIMPLE | test | const | PRIMARY | PRIMARY | 4 | const | 1 | |
  6. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  7. 1 row in set (0.00 sec)

rows

rows 是 MySQL 预估的在执行查询时必须扫描的行数。把所有 rows 列值相乘,可粗略估算整个查询会检查的行数。

对于 InnoDB 类型的表,这个数字只是一个估计,并不总是精确的。

Extra

额外信息,是查询过程的重要补充信息。有几十种可能的输出,完整资料参考 官网 的 EXPLAIN Extra Information 部分。

Using filesort

MySQL 有两种方式生成有序结果:

  • 通过排序操作(ORDER BY 或 GROUP BY)。此时 Extra 中出现“Using filesort”,文件排序。
  • 按索引顺序扫描,通常速度更快。如果 EXPLAIN 出来的 type 列的值为“index”,则说明 MySQL 使用了索引扫描来排序。不要和 Extra 列的“Using index”(覆盖索引,只访问索引即可返回所查询的数据)搞混。

扫描索引本身是很快的,只需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,就不得不每扫描一条索引记录就回表查询一次对应的行,这基本上都是随机 I/O。按索引顺序读数据通常比顺序地全表扫描速度慢,尤其是 I/O 密集型工作负载。

例如,对于 MySQL 的 示例数据库 Sakila,rental 表中的 rental_date 字段是有索引的,return_date 字段是没有索引的,这两个字段区别如下:

  1. mysql> EXPLAIN SELECT * FROM rental WHERE rental_date='2005-05-25' ORDER BY inventory_id, customer_id;
  2. +----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+
  5. | 1 | SIMPLE | rental | ref | rental_date | rental_date | 8 | const | 1 | Using where |
  6. +----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+
  7. 1 row in set (0.00 sec)
  8. mysql> EXPLAIN SELECT * FROM rental WHERE return_date='2005-05-25' ORDER BY inventory_id, customer_id;
  9. +----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+
  10. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  11. +----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+
  12. | 1 | SIMPLE | rental | ALL | NULL | NULL | NULL | NULL | 16305 | Using where; Using filesort |
  13. +----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+
  14. 1 row in set (0.00 sec)

Using temporary

用临时表保存中间结果,常用于 GROUP BY 和 ORDER BY 操作中。尽量避免硬盘临时表的使用。

Not exists

MySQL 能够对查询执行 LEFT JOIN 优化,并且在找到与 LEFT JOIN 条件相匹配的一行后,不会在该表中检查更多行。以下是可以用这种方式进行优化的查询类型的示例:

  1. SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;

Using index

发生覆盖索引,查询的字段完全落入索引,从索引文件中即可获得所需信息,不需要读数据文件。

  1. mysql> EXPLAIN SELECT rental_date FROM rental WHERE rental_date='2005-05-25' ORDER BY inventory_id, customer_id;
  2. +----+-------------+--------+------+---------------+-------------+---------+-------+------+--------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+--------+------+---------------+-------------+---------+-------+------+--------------------------+
  5. | 1 | SIMPLE | rental | ref | rental_date | rental_date | 8 | const | 1 | Using where; Using index |
  6. +----+-------------+--------+------+---------------+-------------+---------+-------+------+--------------------------+
  7. 1 row in set (0.00 sec)

Using where

Extra 列出现“Using where”表示 MySQL 服务器在存储引擎返回行后再应用 WHERE 过滤条件。对于带 WHERE 的 SQL 语句,可能会在存储引擎返回行之前或之后应用 WHERE 过滤条件。

  1. mysql> EXPLAIN SELECT * FROM sakila.actor WHERE last_name="CHASE";
  2. +----+-------------+-------+------+---------------------+---------------------+---------+-------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------------+---------------------+---------+-------+------+-------------+
  5. | 1 | SIMPLE | actor | ref | idx_actor_last_name | idx_actor_last_name | 137 | const | 2 | Using where |
  6. +----+-------------+-------+------+---------------------+---------------------+---------+-------+------+-------------+
  7. 1 row in set (0.00 sec)
  8. mysql> EXPLAIN SELECT * FROM sakila.actor WHERE actor_id = 1;
  9. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  10. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  11. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  12. | 1 | SIMPLE | actor | const | PRIMARY | PRIMARY | 2 | const | 1 | |
  13. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
  14. 1 row in set (0.00 sec)

Impossible where

表示 WHERE 条件总是 FALSE,不能用来获取任何数据。

  1. mysql> EXPLAIN SELECT * FROM test WHERE id=1 AND value="t2";
  2. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  5. | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
  6. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
  7. 1 row in set (0.00 sec)

MySQL 查询性能优化 - EXPLAIN 命令的更多相关文章

  1. MySQL查询性能优化(精)

    MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...

  2. 170727、MySQL查询性能优化

    MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...

  3. MySQL查询性能优化七种武器之索引下推

    前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下: MySQL查询性能优化七种武器之索引潜水 MySQL查询性能优化七种武器之链路追踪 今天要讲的是MySQL的另一种查询性能优化方式 ...

  4. 到底该不该使用存储过程 MySQL查询性能优化一则

    到底该不该使用存储过程   看到<阿里巴巴java编码规范>有这样一条 关于这条规范,我说说我个人的看法 用不用存储过程要视所使用的数据库和业务场景而定的,不能因为阿里巴巴的技术牛逼,就视 ...

  5. MySQL优化技巧之五(mysql查询性能优化)

    对于高性能数据库操作,只靠设计最优的库表结构.建立最好的索引是不够的,还需要合理的设计查询.如果查询写得很糟糕,即使库表结构再合理.索引再合适,也无法实现高性能.查询优化.索引优化.库表结构优化需要齐 ...

  6. MySQL查询性能优化---高性能(二)

    转载地址:https://segmentfault.com/a/1190000011330649 避免向数据库请求不需要的数据 在访问数据库时,应该只请求需要的行和列.请求多余的行和列会消耗MySql ...

  7. 《高性能MySQL》之MySQL查询性能优化

    为什么查询会慢? 响应时间过长.如果把查询看做是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上优化其子任务,要么消除其中一些子任务,要么减少子任务的执行次数, ...

  8. mysql查询性能优化

    mysql查询过程: 客户端发送查询请求. 服务器检查查询缓存,如果命中缓存,则返回结果,否则,继续执行. 服务器进行sql解析,预处理,再由优化器生成执行计划. Mysql调用存储引擎API执行优化 ...

  9. MySQl 查询性能优化相关

    0. 1.参考 提升网站访问速度的 SQL 查询优化技巧 缓存一切数据,读取内存而不是硬盘IO 如果你的服务器默认情况下没有使用MySQL查询缓存,那么你应该开启缓存.开启缓存意味着MySQL 会把所 ...

随机推荐

  1. 实现简单的计算器(设计UI)

    要点说明: 1.一个textedit控件,其余全部是button控件,button布局方式:栅格布局(Grid layout) 2.对窗体的Title进行修改(默认是工程名) 3.在ui文件中设计的U ...

  2. python 迭代器和生成器的区别

    迭代器(iterator)是一个实现了迭代器协议的对象,python的一些内置数据类型(列表,数组,字符串,字典等)都可以通过for语句进行迭代,我们也可以自己创建一个容器,实现了迭代器协议,可以通过 ...

  3. 2019牛客暑期多校训练营(第七场) - C - Governing sand - 平衡树

    5 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 感觉该出14才对,取前k小写成了取前k大. 5 1 5 4 2 5 3 3 5 2 4 5 1 6 5 5 suf=55 res=0 a ...

  4. VINS 估计器之外参初始化

    为何初始化外参 当外参完全不知道的时候,VINS也可以在线对其进行估计(rotation),先在processImage内进行初步估计,然后在后续优化时,会在optimize函数中再次优化. 如何初始 ...

  5. Vue简单封装axios—解决post请求后端接收不到参数问题

    1.在src/下新建api文件夹,api/下新建index.js和public.js 在public.js中: import axios from 'axios'; import qs from 'q ...

  6. Maven将jar包放入本地库

    转自:https://blog.csdn.net/qq_33314107/article/details/73549256 这是由于Oracle授权问题,Maven3不提供Oracle JDBC dr ...

  7. 基于celery的任务管理

    1.celery基本原理 Celery是一个由python编写的简单.灵活.可靠的用来处理大量信息的分布式系统,同时提供了操作和维护分布式系统所需要的工具,说白了就是一个用来管理分布式队列的工具. C ...

  8. 使用GDB调试产生多进程的程序

    如果一个进程fork了多个进程,这时使用GBD工具对程序进行调试会如何呢? 实际上,GDB 没有对多进程程序调试提供直接支持.例如,使用GDB调试某个进程,如果该进程fork了子进程,GDB会继续调试 ...

  9. oracle 汇编04

    General-Purpose Instructions The general-purpose instructions perform basic data movement, memory ad ...

  10. shell getopts用法详解

    本文链接:https://blog.csdn.net/u012703795/article/details/46124519 获取UNIX类型的选项: unix有一个优点就是标准UNIX命令在执行时都 ...