MySQL中使用explain命令分析查询

编程入门 行业动态 更新时间:2024-10-28 14:35:14

MySQL中使用explain<a href=https://www.elefans.com/category/jswz/34/1771323.html style=命令分析查询"/>

MySQL中使用explain命令分析查询

MySQL中使用explain命令分析查询

在MySQL中,使用explain对查询(select)语句进行分析,可以根据分析结果对查询进行优化。

一、数据准备

创建两张表:部门(dept)和员工(emp),表结构如下:

create table dept(dept_id int primary key auto_increment comment '部门编号',dept_name char(20) comment '部门名称'
);
insert into dept(dept_name) values('销售部'),('财务部'),('生产部'),('人事部');create table emp(emp_id int primary key auto_increment comment '员工号',emp_name char(20) not null default '' comment '员工姓名',gender char(2) not null default '男' comment '性别',birth datetime not null default '1990-1-1' comment '出生日期',salary decimal(10,2) not null default 0 comment '工资',address varchar(200) not null default '' comment '通讯地址',dept_id int comment '部门编号'
);create index idx_name on emp(emp_name);
create index idx_birth on emp(birth);
create index idx_deptid_name on emp(dept_id,emp_name);insert into emp(emp_name,gender,birth,salary,address,dept_id) 
values('张晓红','女','1980-1-23',5800,'河南省郑州市中原路10号',1),
('张静静','女','1987-10-3',5400,'河南省新乡市平原路38号',1),
('王云飞','男','1992-11-15',5600,'河南省新乡市人民路28号',1),
('王鹏飞','男','1987-10-1',6800,'河南省新乡市东明大道12号',1),
('王大鹏','男','1989-2-11',5900,'河南省郑州市东风路15号',1),
('王萌萌','女','1986-12-30',5000,'河南省开封市五一路14号',2),
('王大光','男','1988-11-8',6200,'河南省开封市八一路124号',2),
('王小明','男','1998-1-3',4800,'河南省驻马店市雪松路128号',2),
('王娜娜','女','1994-3-5',5200,'河南省驻马店市车站路2号',2),
('刘云飞','男','1992-8-13',6800,'河南省南阳市民生路255号',3),
('张陆军','男','1991-9-6',6200,'河南省南阳市张仲景路14号',3);

二、explain语句的语法

explain语句的基本语法如下:

explain select 语句;

使用explain对查询进行分析,结果如下:

mysql> explain select * from emp -> where salary>(select salary from emp where emp_name='王大光')\G
*************************** 1. row ***************************id: 1select_type: PRIMARYtable: emppartitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 11filtered: 33.33Extra: Using where
*************************** 2. row ***************************id: 2select_type: SUBQUERYtable: emppartitions: NULLtype: ref
possible_keys: idx_namekey: idx_namekey_len: 60ref: constrows: 1filtered: 100.00Extra: NULL
2 rows in set, 1 warning (0.00 sec)

explain显示结果中每个项目的含义为:
1、select_type:select查询的类型,可能会有以下几种情况:
(1)simple:简单的select(没有使用 union或子查询);
(2)primary:最外层的 select;
(3)union:union连接的select查询,除了第一个表外,第二个及以后的表select_type都是union;
(4)dependent union:与union一样,但是这个查询要受到外部查询的影响;
(5)subquery:子查询中的第一个select(from后面的子查询除外);
(6)dependent subquery:表示子查询要受到外部表查询的影响;
(7)derived:from字句中出现的子查询;
2、table:查询引用的表,如果查询使用了别名,则显示的是别名,如果不涉及数据表的操作,显示null;
3、partitions:显示分区表命中的分区情况,非分区表该字段为空(null)。
4、type:表连接类型。从好到差依次为:依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL,除了all之外,其他的type都可以使用到索引。
(1)system:表中只有一行数据或者是空表,且只能用于myisam和memory表;
(2)const:使用唯一索引或者主键进行检索,返回1行记录的等值where条件时为const;
(3)index_merge:表示查询时通过and和or使用了两个以上的索引;
(4)range:索引范围扫描,常见于使用 =, <>, >, >=, <, <=, BETWEEN, IN或like等运算符的查询中;
(5)index:索引全表扫描,把索引从头到尾扫一遍;
(6)all:进行完整的表扫描。
5、possible_keys:在搜索表记录时可能使用哪个索引,possible_keys所包含的索引在实际查询时可能没有被使用。如果为null则表示没有使用任何索引;
6、key:实际使用的索引。如果没有任何索引被用到则为null;
7、key_len:索引的长度。
8、ref:显示使用哪个列或常数与key一起从表中选择行;
9、rows:执行查询时需要检查的行数;
10、filtered:通过条件过滤出的行数的百分比;
11、Extra:显示的信息常用的有:
(1)distinct:在select部分使用了distinc关键字;
(2)no tables used:不带from字句的查询或者from dual查询;
(3)using filesort:排序时无法使用到索引时,常见带order by和group by子句的查询;
(4)using index:查询时使用了覆盖索引,直接通过索引就可以获取查询的数据;
(5)using temporary:使用临时表存储中间结果。

三、举例

(一)子查询
mysql> explain select emp_name,salary from emp where salary>(select avg(salary) from emp)\G
*************************** 1. row ***************************id: 1select_type: PRIMARYtable: emppartitions: NULLtype: ALL
possible_keys: idx_salarykey: NULLkey_len: NULLref: NULLrows: 11filtered: 54.55Extra: Using where
*************************** 2. row ***************************id: 2select_type: SUBQUERYtable: emppartitions: NULLtype: index
possible_keys: NULLkey: idx_salarykey_len: 5ref: NULLrows: 11filtered: 100.00Extra: Using index
2 rows in set, 1 warning (0.01 sec)
(二)union联合查询
mysql> explain select * from emp where dept_id=1 union select * from emp where dept_id=2\G
*************************** 1. row ***************************id: 1select_type: PRIMARYtable: emppartitions: NULLtype: ref
possible_keys: idx_deptid_namekey: idx_deptid_namekey_len: 5ref: constrows: 5filtered: 100.00Extra: NULL
*************************** 2. row ***************************id: 2select_type: UNIONtable: emppartitions: NULLtype: ref
possible_keys: idx_deptid_namekey: idx_deptid_namekey_len: 5ref: constrows: 4filtered: 100.00Extra: NULL
*************************** 3. row ***************************id: NULLselect_type: UNION RESULTtable: <union1,2>partitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLfiltered: NULLExtra: Using temporary
3 rows in set, 1 warning (0.01 sec)
(三)连接查询
mysql> explain select emp_name,salary,dept_name from emp join dept on dept.dept_id=emp.dept_id where dept.dept_id=1\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: deptpartitions: NULLtype: const
possible_keys: PRIMARYkey: PRIMARYkey_len: 4ref: constrows: 1filtered: 100.00Extra: NULL
*************************** 2. row ***************************id: 1select_type: SIMPLEtable: emppartitions: NULLtype: ref
possible_keys: idx_deptid_namekey: idx_deptid_namekey_len: 5ref: constrows: 5filtered: 100.00Extra: NULL
2 rows in set, 1 warning (0.00 sec)
(四)索引覆盖

索引覆盖是查询性能很高的一种情况,当查询所需数据时直接从索引树中检索数据,不需要回写。

mysql> show create table emp\G
*************************** 1. row ***************************Table: emp
Create Table: CREATE TABLE `emp` (`emp_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '员工号',`emp_name` char(20) NOT NULL DEFAULT '' COMMENT '员工姓名',`gender` char(2) NOT NULL DEFAULT '男' COMMENT '性别',`birth` datetime NOT NULL DEFAULT '1990-01-01 00:00:00' COMMENT '出生日期',`salary` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '工资',`address` varchar(200) NOT NULL DEFAULT '' COMMENT '通讯地址',`dept_id` int(11) DEFAULT NULL COMMENT '部门编号',PRIMARY KEY (`emp_id`),KEY `idx_name` (`emp_name`),KEY `idx_deptid_name` (`dept_id`,`emp_name`),   --创建了联合索引KEY `idx_birth` (`birth`),KEY `idx_salary` (`salary`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)mysql> explain select emp_name from emp where dept_id=1\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: emppartitions: NULLtype: ref
possible_keys: idx_deptid_namekey: idx_deptid_namekey_len: 5ref: constrows: 5filtered: 100.00Extra: Using index   ---表示索引覆盖
1 row in set, 1 warning (0.00 sec)

更多推荐

MySQL中使用explain命令分析查询

本文发布于:2024-02-17 09:08:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1693470.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:命令   MySQL   explain

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!