MySQL中explain的几点用法
MySQL里的explain命令内容还是很丰富的,值得好好的挖掘出不少东西来。
本身来说explain就是生成执行计划的内容,如果细看,这个内容和Oracle explain plan for的结果相比还是有差距的。
首先是一个比较实际的用法,查询语句我们可以查看执行计划,如果是DML语句呢,他是直接变更了还是只是生成执行计划而已,明白这一点很重要。
explain 生成DML的执行计划
为了进一步的验证,我们选择3个版本,5.5,5.6,5.7来测试。
首先是初始化数据,这个在不同版本是一模一样的方式。
创建一个表test,插入两行数据。
> create table test(id int,name varchar(20));
Query OK, 0 rows affected (0.01 sec)
> insert into test values(1,'aa'),(2,'bb');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
MySQL 5.5
来看看DML语句的执行计划情况,发现是不支持的。
> explain insert into test values(3,'cc');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into test values(3,'cc')' at line 1
换一个DML比如update,也是不支持的。
> explain update test set name='cc' where id=2;
在此,我们不能得出一个不支持DML的最终结论,我们看看5.6,5.7的结果。
MySQL 5.6 5.6中的结果来看,是支持的,那么最关心的问题,数据会不会变更呢。
> explain insert into test values(3,'cc');
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
查一下数据一目了然。
> select *from test;
+------+------+
| id | name |
+------+------+
| 1 | aa |
| 2 | bb |
+------+------+
2 rows in set (0.00 sec)
而换一个DML,比如update也是类似的效果。不会直接修改数据。
MySQL 5.7
在5.7中又做了一些改变,那就是对于DML的支持更加完善了,你可以通过语句的执行计划可以很清晰的看到是哪一种类型的DML(insert,update,delete),当然insert的执行计划有些鸡肋,因为实在没什么好处理的了。
> explain insert into test values(3,'cc');
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | INSERT | test | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
那看看update的执行计划,可以看出,在当前的表结构情况下,这个语句的执行效率还是十分有限。
> explain update test set name='cc' where id=2;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | UPDATE | test | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
很明显,这个过程是不会修改数据的。
> select *from test;
+------+------+
| id | name |
+------+------+
| 1 | aa |
| 2 | bb |
+------+------+
explain for connection的新特性
如果对于explain开始有了一些感觉,那么我们再来看一个5.7中的新特性,那就是对connection的解析,也就是explain for connection特性。
我们假设一个场景,有一个SQL语句执行效率很差,我们通过show processlist可以看到,但是语句的效率为什么这么差呢,一个行之有效的分析问题的方法就是查看执行计划,好了,回到问题的核心,那就是怎么得到语句的执行计划,这个如果我们按照现有问题的处理方式,那就是查看慢日志,然后再解析。或者使用第三方的工具,来得到一些效果更好一些的报告。
比较纠结的一种情况,就是你看到语句的执行效率很差,但是这么一个过程下来少说也有几分钟,等你快解析出来的时候,发现语句已经返回了。所以实时抓取数据是提升DBA幸福度的一大利器。那我们就模拟一个性能较差的SQL,比如下面的反连接语句,执行效率很差。我们来试着抓取一下执行计划。
> select account
from t_fund_info
where money >= 300
and account not in (select distinct (account)
from t_user_login_record
where add_time >= '2016-06-01');
我们通过mysqladmin pro的方式抓取会话的情况,类似于show processlist的结果,可以很明显看到第一列就是connection id 6346185,我们解析一下这个connection
# mysqladmin pro|grep t_fund_info
| 6346185 | root | localhost | test | Query | 8 | Sending data | select account from t_fund_info where money >= 300 and account not in (select distinct (account) | 0 | 0 |
查看执行计划的情况如下:
> explain for connection 6346185;
+----+-------------+---------------------+------------+------+---------------+------+---------+------+---------+---------
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered
+----+-------------+---------------------+------------+------+---------------+------+---------+------+---------+---------
| 1 | PRIMARY | t_fund_info | NULL | ALL | NULL | NULL | NULL | NULL | 1826980 | 100.00
| 2 | SUBQUERY | t_user_login_record | NULL | ALL | NULL | NULL | NULL | NULL | 1740589 | 33.33
+----+-------------+---------------------+------------+------+---------------+------+---------+------+---------+---------
这样一来就可以得到一个基本的执行计划了,对于分析问题来说还是有一定的效率提升。
- 08-移动端开发教程-移动端适配方案
- 09-移动端开发教程-Sass入门
- 开发者的如何优雅的使用OSX
- Solidity 智能合约开发语言·数据类型
- 以太坊·Rinkeby 测试网络
- TensorFlow强化学习入门(0)——Q-Learning的查找表实现和神经网络实现
- 【云端架构】网站运维之CDN链接鉴权示例入门(PHP)
- 以太坊·单机多实例演示
- TensorFlow强化学习入门(1)——双臂赌博机
- CTF逆向--.NET与Python篇
- CTF逆向--安卓篇
- hackme.inndy.tw的19道web题解(下)
- hackme.inndy.tw的19道web题解(中)
- hackme.inndy.tw的19道web题解(上)
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- MDK更改配色方案
- Apache通过多端口配置多站点
- FatFs-目录下文件扫描
- Python之Bilibili自动更新邮件提醒并任务栏图标「完整代码」
- STC15频率产生器(粗调+微调+数码管显示)完整代码
- PID算法原理、调整规律及代码
- GIT——分布式版本控制系统
- 如何在 PHP 中使用和管理 Cookie
- 玩转 PhpStorm 系列(九):代码调试篇(上)
- 在 PHP 中使用和管理 Session
- STC51单片机中断与定时器配置参考
- 玩转 PhpStorm 系列(十):代码调试篇(下)
- STM32字符串转整数
- Java常用设计模式--代理模式(Proxy Pattern)
- 详解爬取搜狐号自媒体的所有文章