MySQL explain 和 profiling 详解

MySQL explain 和 profiling 详解

mysql explain

MySQL 的 EXPLAIN 是一个用于查询优化的工具,它可以显示 MySQL 数据库如何执行查询。它返回一组关于查询执行计划的信息,包括用到的索引,表的连接顺序以及 MySQL 使用的查询类型。下面是 EXPLAIN 返回的列及其含义:

id

id:查询中每个 SELECT 子句或者操作的唯一标识符。如果 id 相同,那么这些操作在同一个查询中。

select_type

  • select_type:查询的类型,有以下几种类型:
    • SIMPLE:简单 SELECT 查询,不使用 UNION 或子查询等。
    • PRIMARY:最外层的查询,即包含了子查询的查询。
    • UNION:UNION 查询的第二个或后续查询语句,不包括第一个查询语句。
    • DEPENDENT UNION:UNION 查询中的第二个或后续查询语句,依赖于外部查询的结果。
    • UNION RESULT:UNION 的结果集。
    • SUBQUERY:子查询中的第一个 SELECT 语句,结果用于外部查询。
    • DEPENDENT SUBQUERY:子查询中的第一个 SELECT 语句,依赖于外部查询的结果。
    • DERIVED:派生表的 SELECT,MySQL 会将其存储在临时表中。
    • MATERIALIZED:派生表的 SELECT,MySQL 会将其存储在临时表中。
    • UNCACHEABLE SUBQUERY:子查询不可缓存。
  • table:显示查询的表名。
  • partitions:匹配到查询的分区列表。
  • type:表访问的类型,性能从好到坏依次是:
    • system:仅有一行记录的表。
    • const:基于索引进行的等值查询。
    • eq_ref:对于每个查询,使用了索引查找符合条件的一行。
    • ref:非唯一性索引查找,返回匹配某个单独值的所有行。
    • range:使用索引查找一定范围内的行。
    • index:使用索引扫描全表,一般用于ORDER BY和GROUP BY操作。
    • all:全表扫描。
  • possible_keys:可能使用的索引列表。
  • key:实际使用的索引名称。
  • key_len:使用索引的长度。
  • ref:显示索引的哪一列或常量与表列进行比较。
  • rows:估算的行数。
  • filtered:过滤器过滤的行数百分比。
  • Extra:关于 MySQL 如何解析查询的额外信息,包括以下信息:
    • Using index:表示查询中使用了覆盖索引。
    • Using where:表示 MySQL 使用了 WHERE 子句来过滤数据。
    • Using temporary:表示 MySQL 使用了临时表来存储结果集,通常是 GROUP BY 和 ORDER BY 操作的结果。
    • Using filesort:表示 MySQL 使用了文件排序来排序结果集。
    • Using join buffer:表示
    • Using join buffer:表示 MySQL 使用了 join buffer 来处理连接操作。
    • Using sort_union:表示 MySQL 使用了 UNION 查询中的排序优化。
    • Using intersect:表示 MySQL 使用了 UNION 查询中的交集优化。
    • Using index condition:表示 MySQL 使用了索引中的条件进行过滤,这意味着 MySQL 能够在索引中解决查询条件,而无需查找表中的行。
    • Using where with pushed condition:表示 MySQL 将过滤条件下推到了联接前的表中,这可能会更有效地利用索引。
    • Using index for group-by:表示 MySQL 使用了索引来处理 GROUP BY 操作,这通常是一种优化。
    • Using filesort for group-by:表示 MySQL 使用了文件排序来处理 GROUP BY 操作,这通常是不太理想的。
    • Using temporary for filesort:表示 MySQL 使用了临时表来处理 ORDER BY 或 GROUP BY 操作的结果。
    • Using filesort for order by:表示 MySQL 使用了文件排序来处理 ORDER BY 操作,这通常是不太理想的。

下面是一个使用 EXPLAIN 进行查询优化的例子:

EXPLAIN SELECT *
FROM users
JOIN orders ON users.id = orders.user_id
WHERE users.age > 18
ORDER BY orders.created_at DESC
LIMIT 10;

执行上面的语句后,会返回类似如下的输出:

sql
Copy code
+----+-------------+--------+------------+--------+---------------------+---------+---------+------------------------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+--------+---------------------+---------+---------+------------------------+------+----------+--------------------------+
| 1 | SIMPLE | users | NULL | range | PRIMARY,age | age | 4 | NULL | 4 | 100.00 | Using where; Using index |
| 1 | SIMPLE | orders | NULL | ref | user_id,created_at | user_id | 4 | test_db.users.id | 199 | 100.00 | Using index |
+----+-------------+--------+------------+--------+---------------------+---------+---------+------------------------+------+----------+--------------------------+

这个查询通过 JOIN 将用户表和订单表连接起来,只返回年龄大于 18 岁的用户的前 10 个订单,按照订单创建时间倒序排序。通过分析输出结果,我们可以看到 MySQL 使用了用户表的 age 列上的索引来过滤数据,然后使用了订单表的 user_id 列上的索引来查找订单,这个查询使用了索引优化的方法,可以更高效地执行。

MySQL profiling

# 查看是否开启了 profiling
show variables like '%profiling%';
# 开启 profiling
set profiling = 1;
# 执行查询

select * from big_tables where id >= (
    select id from big_tables limit 10000000, 1
) limit 0, 1;

# 查看所有查询的性能数据
show profiles;
# 查看某条查询的详细性能数据
show profile for query 1;
# 查看 cpu, io, memory, block io 等性能数据
show profile cpu, io, memory, block io for query 1;

# 关闭 profiling
set profiling = 0;

使用示例:

mysql> # 查看所有查询的性能数据
show profiles;
+----------+------------+---------------------------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                                             |
+----------+------------+---------------------------------------------------------------------------------------------------+
|        1 | 0.00568250 | show variables like '%profiling%'                                                                 |
|        2 | 1.41488150 | select * from big_tables where id >= (
    select id from big_tables limit 10000000, 1
) limit 0, 1 |
|        3 | 0.00040300 | purge profiles                                                                                    |
|        4 | 0.00016575 | # 清理所有profiling 数据
FLUSH STATEMENT ANALYSIS                                                  |
|        5 | 0.00014875 | FLUSH STATEMENT ANALYSIS                                                                          |
|        6 | 1.41070725 | select * from big_tables where id >= (
    select id from big_tables limit 10000000, 1
) limit 0, 1 |
+----------+------------+---------------------------------------------------------------------------------------------------+
6 rows in set (0.10 sec)
mysql> # 查看某条查询的详细性能数据
show profile for query 6;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000098 |
| Executing hook on transaction  | 0.000034 |
| starting                       | 0.000030 |
| checking permissions           | 0.000009 |
| checking permissions           | 0.000005 |
| Opening tables                 | 0.000059 |
| init                           | 0.000027 |
| System lock                    | 0.000015 |
| optimizing                     | 0.000010 |
| statistics                     | 0.000024 |
| optimizing                     | 0.000004 |
| statistics                     | 0.000008 |
| preparing                      | 0.000016 |
| executing                      | 1.410089 |
| preparing                      | 0.000041 |
| executing                      | 0.000037 |
| end                            | 0.000006 |
| query end                      | 0.000042 |
| waiting for handler commit     | 0.000016 |
| closing tables                 | 0.000014 |
| freeing items                  | 0.000110 |
| cleaning up                    | 0.000019 |
+--------------------------------+----------+
mysql> # 查看 cpu, io, memory, block io 等性能数据
show profile cpu, block io for query 6;
+--------------------------------+----------+----------+------------+--------------+---------------+
| Status                         | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+--------------------------------+----------+----------+------------+--------------+---------------+
| starting                       | 0.000098 | 0.000072 | 0.000025   |            0 |             0 |
| Executing hook on transaction  | 0.000034 | 0.000026 | 0.000009   |            0 |             0 |
| starting                       | 0.000030 | 0.000022 | 0.000007   |            0 |             0 |
| checking permissions           | 0.000009 | 0.000006 | 0.000002   |            0 |             0 |
| checking permissions           | 0.000005 | 0.000004 | 0.000002   |            0 |             0 |
| Opening tables                 | 0.000059 | 0.000044 | 0.000015   |            0 |             0 |
| init                           | 0.000027 | 0.000020 | 0.000007   |            0 |             0 |
| System lock                    | 0.000015 | 0.000010 | 0.000003   |            0 |             0 |
| optimizing                     | 0.000010 | 0.000008 | 0.000003   |            0 |             0 |
| statistics                     | 0.000024 | 0.000018 | 0.000006   |            0 |             0 |
| optimizing                     | 0.000004 | 0.000002 | 0.000001   |            0 |             0 |
| statistics                     | 0.000008 | 0.000006 | 0.000002   |            0 |             0 |
| preparing                      | 0.000016 | 0.000012 | 0.000004   |            0 |             0 |
| executing                      | 1.410089 | 1.412984 | 0.000000   |            0 |             0 |
| preparing                      | 0.000041 | 0.000038 | 0.000000   |            0 |             0 |
| executing                      | 0.000037 | 0.000037 | 0.000000   |            0 |             0 |
| end                            | 0.000006 | 0.000005 | 0.000000   |            0 |             0 |
| query end                      | 0.000042 | 0.000042 | 0.000000   |            0 |             0 |
| waiting for handler commit     | 0.000016 | 0.000016 | 0.000000   |            0 |             0 |
| closing tables                 | 0.000014 | 0.000014 | 0.000000   |            0 |             0 |
| freeing items                  | 0.000110 | 0.000109 | 0.000000   |            0 |             0 |
| cleaning up                    | 0.000019 | 0.000019 | 0.000000   |            0 |             0 |
+--------------------------------+----------+----------+------------+--------------+---------------+
22 rows in set (0.17 sec)

拓展: profiling 数据的条数

一般 profiling 只保留最近 15 条查询的性能数据, 如果需要保留更多的数据, 可以修改 profiling_history_size 变量:

mysql> show variables like '%profiling%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| have_profiling         | YES   |
| profiling              | ON    |
| profiling_history_size | 15    |
+------------------------+-------+
3 rows in set (0.10 sec)
mysql> set global profiling_history_size=20;

本文由mdnice多平台发布

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 本文主要讲述如何通过 explain 命令获取 select 语句的执行计划,通过 explain 我们可以知道以...
    码农随想录阅读 333评论 0 2
  • MySQL实战 目录[https://www.jianshu.com/p/fad04cb06b0b]使用EXPLA...
    香沙小熊阅读 1,423评论 0 11
  • MySQL EXPLAIN命令是查询性能优化不可缺少的一部分,该文主要讲解explain命令的使用及相关参数说明。...
    学编程的小屁孩阅读 567评论 0 0
  • MySQL EXPLAIN命令是查询性能优化不可缺少的一部分,该文主要讲解explain命令的使用及相关参数说明。...
    高广超阅读 78,523评论 2 98
  • MySQL EXPLAIN详解 MySQL EXPLAIN命令是查询性能优化不可缺少的一部分,该文主要讲解expl...
    tanghomvee阅读 508评论 0 1