使用explain来分析SQL语句实现优化SQL语句

Posted 流光瞬息

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用explain来分析SQL语句实现优化SQL语句相关的知识,希望对你有一定的参考价值。

用法:explain sql

作用:用于分析sql语句

mysql> explain select * from quser_1 where loginemail = "[email protected]";
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
| id | select_type | table   | type | possible_keys   | key             | key_len | ref   | rows | Extra                 |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | quser_1 | ref  | loginemailindex | loginemailindex | 302     | const |    1 | Using index condition |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
1 row in set

mysql> 

  

0: id表示执 explain 的一个编号(没有实际意义)

1:table 查询的表名

2:select_type查询类型,是单表查询、联合查询还是子查询,可能会出现以下值:

查询类型 说明
SIMPLE 简单的 select 查询,不使用 union 以及子查询
PRIMARY 最外层的 select 查询(使用到主键作为查询条件)
UNION UNION UNION 中的第二个或者随后的 select 查询,不依赖于外部查询的结果集
DEPENDENT UNION UNION 中的第二个或者随后的 select 查询,依赖于外部查询的结果集
SUBQUERY 子查询中的第一个 select 查询,不依赖于外部查询的结果集
DEPENDENT SUBQUERY 子查询中的第一个 select 查询,依赖于外部 查询的结果集
DERIVED 用于 from 子句里有子查询的情况。 MySQL 会 递归执行这些子查询, 把结果放在临时表里
UNCACHEABLE SUBQUERY 结果集不能被缓存的子查询,必须重新为外 层查询的每一行进行评估
UNCACHEABLE UNION UNION UNION中的第二个或随后的 select 查询,属 于不可缓存的子查询

 

 

例如使用如下表结构:

CREATE TABLE `quser_1` (
  `quserid` int(10) unsigned NOT NULL DEFAULT ‘0‘,
  `username` varchar(64) NOT NULL DEFAULT ‘‘,
  `id` int(10) unsigned NOT NULL DEFAULT ‘0‘,
  `ver` int(10) unsigned NOT NULL DEFAULT ‘0‘,
  `password` varchar(40) NOT NULL DEFAULT ‘‘,
  `randomkey` varchar(30) NOT NULL DEFAULT ‘‘,
  `sealtime` varchar(30) NOT NULL DEFAULT ‘‘,
  `status` tinyint(1) NOT NULL DEFAULT ‘0‘,
  `src` varchar(50) NOT NULL DEFAULT ‘‘,
  `ip` varchar(11) NOT NULL DEFAULT ‘0‘,
  `regtime` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00‘,
  `tastetime` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00‘,
  `lastmodifytime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `loginemail` varchar(100) NOT NULL DEFAULT ‘‘,
  `loginmethod` tinyint(3) unsigned NOT NULL DEFAULT ‘0‘,
  `va` varchar(1000) NOT NULL DEFAULT ‘‘ COMMENT ‘virtual account info‘,
  PRIMARY KEY (`quserid`) KEY_BLOCK_SIZE=1024,
  UNIQUE KEY `username` (`username`) KEY_BLOCK_SIZE=1024,
  KEY `id` (`id`) KEY_BLOCK_SIZE=1024,
  KEY `loginemailindex` (`loginemail`) KEY_BLOCK_SIZE=2048
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8

  

示例1:使用简单查询

mysql> explain select * from quser_1 where loginemail = "[email protected]";
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
| id | select_type | table   | type | possible_keys   | key             | key_len | ref   | rows | Extra                 |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | quser_1 | ref  | loginemailindex | loginemailindex | 302     | const |    1 | Using index condition |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
1 row in set

mysql> 

  

type 说明:

type 说明
system 表仅有一行(=系统表)。这是 const 连接类型的一个特例
const const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System
eq_ref const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System
ref 连接不能基于关键字选择单个行,可能查找 到多个符合条件的行。 叫做 ref 是因为索引要 跟某个参考值相比较。这个参考值或者是一 个常数,或者是来自一个表里的多表查询的 结果值
ref_or_null 如同 ref, 但是 MySQL 必须在初次查找的结果 里找出 null 条目,然后进行二次查找
index_merge 说明索引合并优化被使用了
unique_subquery 在某些 IN 查询中使用此种类型,而不是常规的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr)
index_subquery 在 某 些 IN 查 询 中 使 用 此 种 类 型 , 与 unique_subquery 类似,但是查询的是非唯一 性索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
range 只检索给定范围的行,使用一个索引来选择 行。key 列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可 以使用 range
index 全表扫描,只是扫描表的时候按照索引次序 进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大
all 最坏的情况,从头到尾全表扫描

 

示例2:type 为 const

mysql> explain select * from quser_1 where quserid = "3000096101";
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | quser_1 | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set

  

示例3: type 为 all (这种是要优化和避免的)

mysql> explain select * from quser_1 where src = "pcw";
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | quser_1 | ALL  | NULL          | NULL | NULL    | NULL | 1274 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
1 row in set

  

示例4: type  为 ref

mysql> explain select * from quser_1 where loginemail = ‘[email protected]‘;
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
| id | select_type | table   | type | possible_keys   | key             | key_len | ref   | rows | Extra                 |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | quser_1 | ref  | loginemailindex | loginemailindex | 302     | const |    1 | Using index condition |
+----+-------------+---------+------+-----------------+-----------------+---------+-------+------+-----------------------+
1 row in set

  

prossible_keys:能在该表中使用哪些索引有助于查询

key:实际使用的索引

key_len:索引的长度,在不损失精确性的情况 下,长度越短越好

ref:索引的哪一列被使用了

rows:返回的结果的行数

Extra:其他说明

 

以上是关于使用explain来分析SQL语句实现优化SQL语句的主要内容,如果未能解决你的问题,请参考以下文章

mysql优化:explain分析sql语句执行效率

MySQL Explain详解

7.使用EXPLAIN 来分析SQL和表结构_1

Mysql explain分析sql语句执行效率

sql优化最佳实现(Explain介绍)

mysql优化----explain的列分析