知识大全 Mysql Explain详解
Posted 索引
篇首语:学问之根苦,学问之果甜。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Mysql Explain详解相关的知识,希望对你有一定的参考价值。
Mysql Explain详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
一 语法
explain < table_name >
例如: explain select * from t where id= ;
二 explain输出解释
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
id
我的理解是SQL执行的顺利的标识 SQL从大到小的执行
例如:
mysql> explain select * from (select * from ( select * from t where id= ) a) b;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | t | const | PRIMARY idx_t _id | PRIMARY | | | | |
+ + + + + + + + + + +
很显然这条SQL是从里向外的执行 就是从id= 向上执行
select_type
就是select类型 可以有以下几种
( ) SIMPLE
简单SELECT(不使用UNION或子查询等) 例如:
mysql> explain select * from t where id= ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | const | PRIMARY idx_t _id | PRIMARY | | const | | |
+ + + + + + + + + + +
( ) PRIMARY
我的理解是最外层的select 例如:
mysql> explain select * from (select * from t where id= ) a ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | t | const | PRIMARY idx_t _id | PRIMARY | | | | |
+ + + + + + + + + + +
( ) UNION
UNION中的第二个或后面的SELECT语句 例如
mysql> explain select * from t where id= union all select * from t ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | t | const | PRIMARY idx_t _id | PRIMARY | | const | | |
| | UNION | t | ALL | NULL | NULL | NULL | NULL | | |
|NULL | UNION RESULT | <union > | ALL | NULL | NULL | NULL | NULL | NULL | |
+ + + + + + + + + + +
( ) DEPENDENT UNION
UNION中的第二个或后面的SELECT语句 取决于外面的查询
mysql> explain select * from t where id in (select id from t where id= union all select id from t ) ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | t | ALL | NULL | NULL | NULL | NULL | | Using where |
| | DEPENDENT SUBQUERY | t | const | PRIMARY idx_t _id | PRIMARY | | const | | Using index |
| | DEPENDENT UNION | t | eq_ref | PRIMARY idx_t _id | PRIMARY | | func | | Using where; Using index |
|NULL | UNION RESULT | <union > | ALL | NULL | NULL | NULL | NULL | NULL | |
+ + + + + + + + + + +
( ) UNION RESULT
UNION的结果
mysql> explain select * from t where id= union all select * from t ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | t | const | PRIMARY idx_t _id | PRIMARY | | const | | |
| | UNION | t | ALL | NULL | NULL | NULL | NULL | | |
|NULL | UNION RESULT | <union > | ALL | NULL | NULL | NULL | NULL | NULL | |
+ + + + + + + + + + +
( ) SUBQUERY
子查询中的第一个SELECT
mysql> explain select * from t where id = (select id from t where id= ) ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | t | const | PRIMARY idx_t _id | PRIMARY | | const | | |
| | SUBQUERY | t | const | PRIMARY idx_t _id | PRIMARY | | | | Using index |
+ + + + + + + + + + +
( ) DEPENDENT SUBQUERY
子查询中的第一个SELECT 取决于外面的查询
mysql> explain select id from t where id in (select id from t where id= ) ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | t | index | NULL | PRIMARY | | NULL | | Using where; Using index |
| | DEPENDENT SUBQUERY | t | const | PRIMARY idx_t _id | PRIMARY | | const | | Using index |
+ + + + + + + + + + +
( ) DERIVED
派生表的SELECT(FROM子句的子查询)
mysql> explain select * from (select * from t where id= ) a ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | t | const | PRIMARY idx_t _id | PRIMARY | | | | |
+ + + + + + + + + + +
table
显示这一行的数据是关于哪张表的
有时不是真实的表名字 看到的是derivedx(x是个数字 我的理解是第几步执行的结果)
mysql> explain select * from (select * from ( select * from t where id= ) a) b;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | t | const | PRIMARY idx_t _id | PRIMARY | | | | |
+ + + + + + + + + + +
type
这列很重要 显示了连接使用了哪种类别 有无使用索引
从最好到最差的连接类型为const eq_reg ref range indexhe和ALL
( ) system
这是const联接类型的一个特例 表仅有一行满足条件 如下(t 表上的id是 primary key)
mysql> explain select * from (select * from t where id= ) a ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | PRIMARY | <derived > | system | NULL | NULL | NULL | NULL | | |
| | DERIVED | t | const | PRIMARY idx_t _id | PRIMARY | | | | |
+ + + + + + + + + + +
(nst
表最多有一个匹配行 它将在查询开始时被读取 因为仅有一行 在这行的列值可被优化器剩余部分认为是常数 const表很快 因为它们只读取一次!
const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时 在下面的查询中 tbl_name可以用于const表
SELECT * from tbl_name WHERE primary_key=
SELECT * from tbl_name WHERE primary_key_part = 和 primary_key_part =
例如:
mysql> explain select * from t where id= ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | const | PRIMARY idx_t _id | PRIMARY | | const | | |
+ + + + + + + + + + +
( ) eq_ref
对于每个来自于前面的表的行组合 从该表中读取一行 这可能是最好的联接类型 除了const类型 它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY
eq_ref可以用于使用= 操作符比较的带索引的列 比较值可以为常量或一个使用在该表前面所读取的表的列的表达式
在下面的例子中 MySQL可以使用eq_ref联接来处理ref_tables
SELECT * FROM ref_table other_table
WHERE ref_table key_column=lumn;
SELECT * FROM ref_table other_table
WHERE ref_table key_column_part =lumn
AND ref_table key_column_part = ;
例如
mysql> create unique index idx_t _id on t (id) ;
Query OK rows affected ( sec)
Records: Duplicates: Warnings:
mysql> explain select * from t t where t id=t accountid;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | ALL | NULL | NULL | NULL | NULL | | |
| | SIMPLE | t | eq_ref | PRIMARY idx_t _id | idx_t _id | | dbatest t accountid | | |
+ + + + + + + + + + +
( ) ref
对于每个来自于前面的表的行组合 所有有匹配索引值的行将从这张表中读取 如果联接只使用键的最左边的前缀 或如果键不是UNIQUE或PRIMARY KEY(换句话说 如果联接不能基于关键字选择单个行的话) 则使用ref 如果使用的键仅仅匹配少量行 该联接类型是不错的
ref可以用于使用=或<=>操作符的带索引的列
在下面的例子中 MySQL可以使用ref联接来处理ref_tables
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table other_table
WHERE ref_table key_column=lumn;
SELECT * FROM ref_table other_table
WHERE ref_table key_column_part =lumn
AND ref_table key_column_part = ;
例如:
mysql> drop index idx_t _id on t ;
Query OK rows affected ( sec)
Records: Duplicates: Warnings:
mysql> create index idx_t _id on t (id) ;
Query OK rows affected ( sec)
Records: Duplicates: Warnings:
mysql> explain select * from t t where t id=t accountid;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | ALL | NULL | NULL | NULL | NULL | | |
| | SIMPLE | t | ref | PRIMARY idx_t _id | idx_t _id | | dbatest t accountid | | |
+ + + + + + + + + + +
rows in set ( sec)
( ) ref_or_null
该联接类型如同ref 但是添加了MySQL可以专门搜索包含NULL值的行 在解决子查询中经常使用该联接类型的优化
在下面的例子中 MySQL可以使用ref_or_null联接来处理ref_tables
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
( ) index_merge
该联接类型表示使用了索引合并优化方法 在这种情况下 key列包含了使用的索引的清单 key_len包含了使用的索引的最长的关键元素
例如:
mysql> explain select * from t where id= or accountid= ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | index_merge | idx_t _id idx_t _accountid | idx_t _id idx_t _accountid | | NULL | | Using union(idx_t _id idx_t _accountid); Using where |
+ + + + + + + + + + +
row in set ( sec)
( ) unique_subquery
该类型替换了下面形式的IN子查询的ref
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数 可以完全替换子查询 效率更高
( ) index_subquery
该联接类型类似于unique_subquery 可以替换IN子查询 但只适合下列形式的子查询中的非唯一索引
value IN (SELECT key_column FROM single_table WHERE some_expr)
( ) range
只检索给定范围的行 使用一个索引来选择行 key列显示使用了哪个索引 key_len包含所使用索引的最长关键元素 在该类型中ref列为NULL
当使用= <> > >= < <= IS NULL <=> BEEEN或者IN操作符 用常量比较关键字列时 可以使用range
mysql> explain select * from t where id= or id= ;
+ + + + + + + + + + +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ + + + + + + + + + +
| | SIMPLE | t | range | PRIMARY idx_t _id | idx_t _id | | NULL | | Using where |
+ + + + + + + + + + +
row in set ( sec)
( ) index
该联接类型与ALL相同 除了只有索引树被扫描 这通常比ALL快 因为索引文件通常比数据文件小
当查询只使用作为单索引一部分的列时 MySQL可以使用该联接类型
( ) ALL
对于每个来自于先前的表的行组合 进行完整的表扫描 如果表是第一个没标记const的表 这通常不好 并且通常在它情况下很差 通常可以增加更多的索引而不要使用ALL 使得行能基于前面的表中的常数值或列值被检索出
possible_keys
possible_keys列指出MySQL能使用哪个索引在该表中找到行 注意 该列完全独立于EXPLAIN输出所示的表的次序 这意味着在possible_keys中的某些键实际上不能按生成的表次序使用
如果该列是NULL 则没有相关的索引 在这种情况下 可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能 如果是这样 创造一个适当的索引并且再次用EXPLAIN检查查询
key
key列显示MySQL实际决定使用的键(索引) 如果没有选择索引 键是NULL 要想强制MySQL使用或忽视possible_keys列中的索引 在查询中使用FORCE INDEX USE INDEX或者IGNORE INDEX
key_len
key_len列显示MySQL决定使用的键长度 如果键是NULL 则长度为NULL
使用的索引的长度 在不损失精确性的情况下 长度越短越好
ref
ref列显示使用哪个列或常数与key一起从表中选择行
rows
rows列显示MySQL认为它执行查询时必须检查的行数
Extra
该列包含MySQL解决查询的详细信息 下面详细
( ) Distinct
一旦MYSQL找到了与行相联合匹配的行 就不再搜索了
( ) Not exists
MYSQL优化了LEFT JOIN 一旦它找到了匹配LEFT JOIN标准的行
就不再搜索了
( ) Range checked for each
Record(index map:#)
没有找到理想的索引 因此对于从前面表中来的每一个行组合 MYSQL检查使用哪个索引 并用它来从表中返回行 这是使用索引的最慢的连接之一
( ) Using filesort
看到这个的时候 查询就需要优化了 MYSQL需要进行额外的步骤来发现如何对返回的行排序 它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
( ) Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的 这发生在对表的全部的请求列都是同一个索引的部分的时候
( ) Using temporary
看到这个的时候 查询需要优化了 这里 MYSQL需要创建一个临时表来存储结果 这通常发生在对不同的列集进行ORDER BY上 而不是GROUP BY上
( ) Using where
cha138/Article/program/MySQL/201311/29305相关参考
MySQL数据库存储引擎详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 存储引擎是什么?
MySQL的数据类型和建库策略详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 无论是在小得可
知识大全 MySQL事件调度器Event Scheduler详解
MySQL事件调度器EventScheduler详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
数据库学习:MySQLJoin详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 还是先Crea
详解MySQL数据库提升性能的八种方法[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 使用
详解MySQL数据库提升性能的八种方法[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 选取
知识大全 IBM DB2事件监视器及explain plan的使用[1]
IBMDB2事件监视器及explainplan的使用[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一
知识大全 IBM DB2事件监视器及explain plan的使用[2]
IBMDB2事件监视器及explainplan的使用[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一
MySQL中文参考手册---MySQL文件系统 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 这
MySQL学习笔记-MySQL的安装(1) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 由于我