0

实战Mysql Explain

 2 years ago
source link: https://haojunsheng.github.io/2021/12/mysql-explain/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Mysql Explain是非常重要的,在我们写完Mysql命令之后,帮我们分析Sql的性能。

其使用是十分简单的,在sql语句前面加上explain即可。

image-20220110203026199

我们准备了一张表用于演示。

create table myOrder
(
    id int auto_increment primary key,
    user_id int,
    order_id int,
    order_status tinyint,
    create_date datetime
);
create index idx_userid_order_id_createdate on myOrder(user_id,order_id,create_date);

id:select子句或者操作的顺序

  • id相同:执行顺序自上而下
  • id不同:id值越大优先级越高,越先被执行

select_type查询类型

  • simple:不需要union操作或者不包含子查询
mysql> explain select * from myOrder where order_id=1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | order | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
  • primary:需要union操作或者包含子查询

    mysql> explain select (select user_id from order) from myOrder;
    +----+-------------+------------+------------+-------+---------------+--------------------------------+---------+------+------+----------+-------------+
    | id | select_type | table      | partitions | type  | possible_keys | key                            | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+------------+------------+-------+---------------+--------------------------------+---------+------+------+----------+-------------+
    |  1 | PRIMARY     | order | NULL       | index | NULL          | idx_userid_order_id_createdate | 16      | NULL |    1 |   100.00 | Using index |
    |  2 | SUBQUERY    | order | NULL       | index | NULL          | idx_userid_order_id_createdate | 16      | NULL |    1 |   100.00 | Using index |
    +----+-------------+------------+------------+-------+---------------+--------------------------------+---------+------+------+----------+-------------+
    2 rows in set, 1 warning (0.00 sec)
    
  • union:多表查询

    mysql> explain select * from myOrder union select * from myOrder;
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    | id | select_type  | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    |  1 | PRIMARY      | myOrder    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
    |  2 | UNION        | myOrder    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL            |
    | NULL | UNION RESULT | <union1,2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    3 rows in set, 1 warning (0.01 sec)
    

table表名

前面有,不在赘述。

partitions分区信息

type类型

  • System:只有一行数据或者是空表
  • const:使用唯一索引或者主键
  • eq_ref:唯一性索引扫描,对于每个索引键,表示只有一条记录与之匹配,常见于主键或唯一索引扫描
  • ref:非唯一性索引扫描,返回匹配某个单独值的所有行
  • range:只检索给定范围的行,使用一个索引来选择行,一般就是在where语句中出现了between、<、>、in等的查询
  • index:从索引中读取
  • all:从硬盘中读取,遍历全表

possible_keys

查询中可能使用的索引。

查询中实际使用的索引。

key_len

查询的索引长度。

预估的扫描行数

Extra

Using filesort文件排序

额外的排序

Using index覆盖索引

where筛选条件是索引的前导列

mysql> explain select user_id,order_id,create_date from myOrder where user_id=1;
+----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------------+
| id | select_type | table      | partitions | type | possible_keys                  | key                            | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | test_order | NULL       | ref  | idx_userid_order_id_createdate | idx_userid_order_id_createdate | 5       | const |    1 |   100.00 | Using index |
+----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

Using where;Using index,覆盖索引

  • where筛选条件是索引列之一但是不是索引的不是前导列

    mysql> explain select user_id,order_id,create_date from myOrder where order_id=1;
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    | id | select_type | table      | partitions | type  | possible_keys                  | key                            | key_len | ref  | rows | filtered | Extra                    |
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    |  1 | SIMPLE      | test_order | NULL       | index | idx_userid_order_id_createdate | idx_userid_order_id_createdate | 16      | NULL |    1 |   100.00 | Using where; Using index |
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    1 row in set, 1 warning (0.00 sec)
    
  • where筛选条件是索引的前导列,但是是一个范围

    mysql> explain select user_id,order_id,create_date from myOrder where user_id>1 and user_id<5;
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    | id | select_type | table      | partitions | type  | possible_keys                  | key                            | key_len | ref  | rows | filtered | Extra                    |
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    |  1 | SIMPLE      | test_order | NULL       | index | idx_userid_order_id_createdate | idx_userid_order_id_createdate | 16      | NULL |    1 |   100.00 | Using where; Using index |
    +----+-------------+------------+------------+-------+--------------------------------+--------------------------------+---------+------+------+----------+--------------------------+
    1 row in set, 1 warning (0.01 sec)
    

Using index condition:需要回表

  • Using where,查询的列未被索引覆盖,where筛选条件非索引的前导列或者是非索引列

    mysql> explain select user_id,order_id,create_date,order_status from myOrder where order_id=1;
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
    | id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | test_order | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
    +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
  • NULL,查询的列未被索引覆盖,where条件是索引的前导列

    mysql> explain select user_id,order_id,create_date,order_status from myOrder where user_id=1;
    +----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------+
    | id | select_type | table      | partitions | type | possible_keys                  | key                            | key_len | ref   | rows | filtered | Extra |
    +----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | test_order | NULL       | ref  | idx_userid_order_id_createdate | idx_userid_order_id_createdate | 5       | const |    1 |   100.00 | NULL  |
    +----+-------------+------------+------------+------+--------------------------------+--------------------------------+---------+-------+------+----------+-------+
    1 row in set, 1 warning (0.01 sec)
    

Using temporary,表示的是需要使用临时表

这里比较复杂,可能是内存临时表,也可能是磁盘临时表。

  • 内存临时表:指的是使用Memory引擎的表。
  • 磁盘临时表:一般使用Innodb引擎。

Mysql官方文档


Recommend

  • 37
    • www.tuicool.com 5 years ago
    • Cache

    MySQL中Explain初识

    Index MySQL索引的基本操作 CREATE INDEX idx_price on OrderItems(item_price); ALTER TABLE OrderItems DROP INDEX idx_order_num_price; Explai...

  • 31
    • www.tuicool.com 4 years ago
    • Cache

    Using Explain Analyze in MySQL 8

    In MySQL 8.0.18 there is a new feature called Explain Analyze

  • 37
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    mysql调优之利器explain

    MySql调优很大一部分是索引调整,而通过mysql explain语句能够知晓sql的效率,所以掌握它很重要。 explian输出的一些属性很关键,举例一些我认为很重要的。 1:type 其中eq_ref表示查询一般只有一行匹配,适用于主键或...

  • 7
    • www.justdojava.com 3 years ago
    • Cache

    从 LeetCode 的题目再看 MySQL Explain

    从 LeetCode 的题目再看 MySQL Explain 发表于...

  • 8
    • mednoter.com 3 years ago
    • Cache

    MySQL Explain 详解

    MySQL Explain 详解 本周五做的一次关于 MySQL explain 的技术分享。 下载 Objective give you the hunch: bad query? best query?

  • 5
    • segmentfault.com 3 years ago
    • Cache

    MySQL执行计划【explain】

    MySQL执行计划【explain】发布于 8 月 7 日本文已经收录到

  • 5
    • segmentfault.com 2 years ago
    • Cache

    MySQL: 使用explain 优化查询性能

    Explain 介绍为了优化MySQL的SQL语句的执行性能,MySQL提供了explain关键字用于查看SQL的执行计划。格式如下:{EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] {EXPLAIN | DESCRIBE | DESC} [explain_type] {exp...

  • 2

    MySQL EXPLAIN结果集分析 - 附带大量案例 大量实例助你看懂Explain的输出内容,轻松搞定慢查询 EXPLAIN:查看SQL语句的执行计划 EXPLAIN命令可以帮助我们深入了解MySQL基于开销的优化器,还可以获...

  • 2

    V2EX  ›  MySQL MySQL explain key_len 和联合索引问题   oneisall8955 · 3 小时 55 分钟前...

  • 5

    Explaining EXPLAIN (And an Answer to a Bonus Question) Back to the Blog

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK