知识大全 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数据库存储引擎详解

MySQL数据库存储引擎详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  存储引擎是什么?  

知识大全 MySQL的数据类型和建库策略详解

MySQL的数据类型和建库策略详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  无论是在小得可

知识大全 MySQL事件调度器Event Scheduler详解

MySQL事件调度器EventScheduler详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 数据库学习:MySQL Join详解

数据库学习:MySQLJoin详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  还是先Crea

知识大全 详解MySQL数据库提升性能的八种方法[2]

详解MySQL数据库提升性能的八种方法[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  使用

知识大全 详解MySQL数据库提升性能的八种方法[1]

详解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 文件系统

MySQL中文参考手册---MySQL文件系统  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  这

知识大全 MySQL学习笔记-MySQL的安装(1)

MySQL学习笔记-MySQL的安装(1)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  由于我