,,mysql中explain用法详解

,,mysql中explain用法详解

EXPLAIN用于在SELECT语句中为每个表返回一行信息。表是按照MySQL在查询处理过程中读取它们的顺序列出的。

如果您在select语句前放置关键字explain,mysql将解释它如何处理select,并提供有关表如何连接以及连接顺序的信息。

explain的每一个输出行都提供了关于一个表的信息,并且每一行都包括以下列:

1,id选择标识符。这是select的查询序列号。2、select_type可以是以下任意类型:simple简单选择(不使用union或子查询)、primary的最外层select union中的第二个或后续select语句或dependent union union中的第二个或后续select语句取决于外部查询union结果union的结果。子查询中的第一个select依赖于导出表的select(from子句的子查询)3的外部查询,以及由output by table行引用的表。4、类型加入类型。下面是各种连接类型,从最好的类型到最差的类型排序:系统表只有一行(=系统表)。这是常量连接类型的一个特例。Const表最多有一个匹配行,将在查询开始时读取。因为只有一行,所以优化器的其余部分可以将该行中的列值视为常量。Const表很快,因为它们只被读取一次!Eq_ref对于上一个表中的每个行组合,从该表中读取一行。除了const类型,这可能是最好的连接类型。它用于连接索引的所有部分,并且索引是唯一的或主keyref。对于上一个表中的每个行组合,将从该表中读取具有匹配索引值的所有行。如果联接只使用键最左边的前缀,或者如果键不是唯一键或主键(换句话说,如果联接不能基于关键字选择单个行),则使用ref。如果使用的键只匹配几行,这种连接类型很好。Ref可用于使用=或=运算符的索引列。如果该列为空,则没有相关的索引。在这种情况下,您可以通过检查where子句来查看它是否引用了一些列或适合索引的列,从而提高查询性能。如果是这样,创建一个适当的索引,并再次用explain检查查询键列,以显示实际上由mysql决定的键(索引)。如果没有选择索引,则键为空。要强制mysql使用或忽略possible_keys列中的索引,请在查询中使用force index、use index或ignore index。5、rows rows列显示了mysql认为在执行查询时必须检查的行数。

以上简单介绍了mysql中explain语句的用法,希望对大家有所帮助。

对mysql explain讲的比较清楚

在explain的帮助下,您知道何时向表中添加索引,这样您就可以使用索引来查找记录并使select运行得更快。如果某些问题是由于索引使用不当造成的,可以运行analyze table来更新表的统计信息,比如键的基数,这可以帮助您在优化中做出更好的选择。

Explain返回一行记录,其中包括select语句中使用的每个表的信息。这些表按照在mysql执行的查询中读取的顺序在结果中列出。Mysql使用单扫(多连接)的方法来解决连接。这意味着mysql从第一个表中读取一条记录,然后在第二个表中查找相应的记录,然后在第三个表中查找,依此类推。当扫描完所有的表后,它输出所选的字段,并回溯所有的表,直到找不到为止,因为有些表中可能有多个匹配的记录,将从那个表中读取下一条记录,然后从下一个表继续处理。在mysql版本中,explain输出的结果格式发生了变化,更适合union语句、子查询和派生表的结构。更值得注意的是,它添加了两个新字段:id和select_type。当您使用mysql4.1之前的版本时,您不会看到这些字段。解释结果的每条记录显示每个表的相关信息,每条记录包含以下字段:

Id该选择的标识符。在查询中,每个选择都有一个顺序值。select_type select可能有以下几种类型:简单:简单选择(不使用联合或子查询)

主要的:最外面的选择。

联合:选择后的第二层使用联合。

从属union:union语句中的第二个select,它依赖于外部子查询。

子查询:子查询中的第一个选择

从属子查询:子查询中的第一个子查询依赖于外部子查询。

Derived:派生表SELECT(from子句中的子查询)

记录表查询引用的表。

类型表连接类型。下面列出了不同类型的表连接,从最好到最差依次为:

系统:表只有一行记录(等于系统表)。这是常量表连接类型的一个特例。

Const:表中最多只有一条匹配的记录,会在查询开始时读出。因为只有一行记录,所以这一行记录的字段值在剩下的优化程序中可以看作一个常数值。Const表查询速度非常快,因为只需要读取一次!当与主键或唯一索引相比有固定值时,使用Const。在以下查询中,tbl_name是C表:select * from TBL _ name其中primary _ key=1;select * from TBL _ name其中primary_key_part1=1,primary _ key _ part2=2

Eq_ref:将从该表中读出一行记录,并与从前一个表中读出的记录相结合。与const类型不同,这是最好的连接类型。它用于连接索引的所有部分,并且该索引是主键或唯一类型。当进行“=”比较时,Eq_ref可用于检索字段。比较值可以是固定值或表达式。表中的字段可用于表达式中。他们是在读表之前准备好的。在以下示例中,mysql使用eq_ref连接来处理ref_table:

select * from ref_table,other _ table where ref _ table . key _ column=other _ table . column;select * fromref_table,other _ table where ref _ table . key _ column _ part 1=other _ table . column and ref _ table . key _ column _ part 2=1;

Ref:该表中与搜索值匹配的所有记录都将被取出,并与从前一个表中取出的记录相结合。当链接器使用键最左边的前缀或者键不是主键或唯一索引(换句话说,链接器不能根据键值只获得一条记录)时,使用Ref。当根据键值只找到少量匹配记录时,这是一种很好的连接类型。当使用=运算符比较检索字段时,也可以使用Ref。下面的例子中,mysql会使用ref来处理ref _ table: select * from ref _ table其中key _ column=exprselect * fromref_table,other _ table where ref _ table . key _ column=other _ table . column;select * fromref_table,other _ table where ref _ table . key _ column _ part 1=other _ table . column and ref _ table . key _ column _ part 2=1;

Ref_or_null:这种连接类型类似于Ref,只是mysql在检索时会额外搜索包含null值的记录。这种连接类型的优化从mysql4.1.1开始,常用于子查询。在下面的例子中,mysql使用ref_or_null类型处理ref _ table: select * from ref _ table其中key _ column=expr或key _ column为null;

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)

范围:只取出给定范围内的记录。使用索引获取记录。关键字段指示使用哪个索引。key_len字段包含所用密钥的最长部分。在此类型中,ref字段的值为null。Range用于比较具有以下任何运算符的殖民的字段=、=、=、=、is null、=、between或in:select * from TBL _ name where key _ column=10;select * fromtbl _ name其中key_column介于10和20之间;select * from TBL _ name where key _ column in(10,20,30);select * from TBL _ name where key _ part 1=10 and key _ part 2 in(10,20,30);

Index:连接类型与all相同,只是它只扫描索引树。它通常比所有文件都快,因为索引文件通常比数据文件小。当mysql查询的字段知识是单独索引的一部分时,使用这种连接类型。

All:将扫描所有表,以便与从上一个表中获得的记录相结合。这时,如果第一个表没有被标识为const,就不好了。在其他情况下,通常是非常糟糕的。通常,您可以通过添加索引来避免all,从而更快地从表中获取记录。

可能的键

possible_keys字段指的是mysql在搜索表记录时可能使用的索引。注意,这个字段完全独立于explain显示的表顺序。这意味着在实际使用中可能不会用到包含在possible_keys中的索引。如果该字段的值为null,则意味着没有使用任何索引。在这种情况下,您可以检查where子句中的哪些字段适合添加索引以提高查询性能。就是这样,创建索引,然后用explain检查。有关详细信息,请参见“14.2.2更改表语法”一章。如果您想查看表有哪些索引,可以通过show index from tbl_name来查看它们。

key字段显示了mysql实际使用的索引。当不使用索引时,该字段的值为空。要强制mysql使用或忽略possible_keys字段中的索引列表,可以在查询语句中使用关键字force index、use index或ignore index。如果是myisam和bdb类型的表,可以使用analyzetable帮助分析哪个索引更好。如果是myisam类型的表,运行命令myisamchk - analyze具有相同的效果。有关详细信息,请参见“14.5.2.1分析表syntax”和“5.7.2表维护和故障恢复”章节。

key_len

key_len字段显示了mysql使用的索引长度。当键字段的值为空时,索引的长度为空。注意key_len的值可以告诉你mysql实际上会在联合索引中使用哪些索引。

裁判员

ref字段显示哪些字段或常量用于查询和记录带有关键字的表。

rows行字段显示了mysql认为应该在查询中检索的记录数。

extra

该字段在查询中显示有关mysql的附加信息。以下是对该字段几个不同值的解释:

Distinct:mysql在找到当前记录的第一条匹配union结果的记录后,不会搜索其他记录。

Not exists:当MySQL在查询时进行左连接优化时,在当前表中找到有前一条记录的左连接条件后,不会再搜索更多的记录。以下是此类查询的一个示例:select * from t1 left join T2 on t1 . id=t2.id其中T2 . id为空;

假设t2.id被定义为not null。在这种情况下,mysql将扫描表t1,并使用t1.id的值来查找t2中的记录。当在t2中找到匹配记录时,意味着t2。ID肯定不全是空的,所以在T2不会搜索具有相同ID值的其他记录。也可以说,mysql只需要在t2中对t1中的每条记录查找一次,而不管t2中实际存在多少条匹配的记录。

检查每个记录的范围(索引映射:#)

Mysql没有找到合适的可用索引。相反,对于前一个表的每个行连接,它将进行测试以确定使用哪个索引(如果有的话),并使用该索引从表中获取记录。这个过程不会很快,但总比没有任何索引的表连接快。

使用filesort: mysql需要再做一次来获得有序的记录。排序程序根据连接类型遍历所有记录,并存储要排序的键和指向满足where条件的所有记录的指针。这些键已经排序了,对应的记录会按照排序的顺序取出。详见“7 . 2 . 9 MySQL如何优化order by”。使用索引

字段信息直接从索引树中的信息获得,而不是扫描实际记录。当使用这种策略进行查询时,这些字段是独立索引的一部分。

使用临时:mysql需要创建一个临时表来存储结果以完成查询。当查询包含以不同方式列出字段的groupby和order by子句时,通常会发生这种情况。使用哪里

Where子句将用于限制哪些记录匹配下一个表或发送给客户机。除非您特别希望获取或检查该表类型的所有记录,否则当查询的额外字段的值未使用where并且表连接类型为all或index时,可能会出现问题。

如果想让查询尽可能快,应该注意额外字段的值使用filesort和使用temporary的情况。

通过explain结果中rows字段的值的乘积,您可以大致了解这个连接的执行情况。它可以大致告诉我们mysql在查询过程中会查询多少条记录。如果使用系统变量max_join_size来获得查询结果,则该乘积还可以用于确定将执行哪些多表select语句。以下示例显示了如何通过explain提供的信息来极大地优化多表连接查询的性能。假设您有下面的select语句,并且您将使用explain来测试它:Explain Select TT。机票号码,TT。时间到了,TT。项目参考,TT。预计装运日期,TT。实际发货日期,TT。Clientid,tt.servicecodes,tt.repetitiveid,tt.currentprocess,TT . current ppers TT . record volume,tt.dpprinted,et.country,et_1.country,do.custname from tt,et,et as et_1,do其中tt.submittime为null,tt.actualpc=et.employid和tt.assignedpc=et_1.employid和TT . clientid=do . custnmbr;

在本例中,首先做出以下假设:

要比较的字段定义如下:表列列类型TT实际PC Char (10) TT分配的PC Char (10) TT Clientid Char (10) et已用Char (15) Do CustnMBR Char (15)

数据表的索引如下:表索引TT实际PC TT分配PC TT Clientid et Employed(主键)do CustnMBR(主键)

tt.actualpc的值分布不均匀。

在采取任何优化措施之前,解释分析的结果如下:表类型possible _ keys key _ len ref rows extra et all primary null null 74 do all primary null null 2135 et _ 1 all prim。ary null null null 74 tt所有assignedpc,null null null 3872 clientid,检查每个记录的实际pc范围(键映射:35)

因为field type的值对于每个表都是all,所以这个结果意味着mysql对于所有表都做了Ducal的产品;即每条记录的组合。这将需要很长时间,因为需要扫描每个表中记录总数的乘积之和。在这种情况下,它的乘积是74 * 2135 * 74 * 3872=45,268,558,720条记录。如果数据表更大,可想而知需要多长时间。这里有一个问题,当字段的定义相同时,mysql可以更快地对这些字段使用索引(对于isam类型的表,除非字段的定义完全相同,否则不会使用索引)。在这个前提下,varchar和char是相同的,除非它们定义的长度不同。由于tt.actualpc定义为char(10),et.employid定义为char(15),所以它们的长度不一致。要解决这个问题,需要使用alter table将actualpc的长度从10个字符增加到15个字符:MySQL Alter Table TT修改actual PC Varchar(15);

现在tt.actualpc和et.employid都是varchar(15)。再次执行explain语句以查看结果:table type possible _ keys key _ len ref rows extra TT all assigned PC,null null null 3872 using client,where actual PC do all primary null null null 2135 range checked for each record(key map:1)et _ 1 all primary null null 74 range checked for each record(key map:1)et eq _ ref primary primary 15 TT . actual PC 1

这还不够,还可以做得更好:现在rows value乘积已经减少了74倍。这个查询需要2秒钟。第二个变化是消除比较TT时字段长度的不一致。AssignedPC=ET _ 1。employed and TT . clientid=do . custnmbr:MySQL alter table TT修改assignedPC varchar (15),-修改clientid varchar(15);

解释的结果如下:表类型possible _ keys key _ len ref rows extra et all primary null null null 74 TT ref assigned PC,actual PC 15 et . employid 52 using clientid,其中actual PC et _ 1 eq _ ref primary primary 15 TT . assigned PC 1 do eq _ ref primary 15 TT . clientid 1

这似乎是能做到的最好结果。剩下的问题是,mysql认为默认情况下tt.actualpc字段的值是均匀分布的,而表tt不是。幸运的是,我们可以很容易地让mysql分析索引的分布:mysql分析表TT;

到目前为止,表连接已经优化得很完美了,解释的结果如下:表类型possible _ keys key _ len ref rows extra TT all assigned PC null null null 3872 using client,其中actual PC et eq _ ref primary 15 TT . actual PC 1 et _ 1 eq _ ref primary 15 TT . assigned PC 1 do eq _ ref primary 15 TT . clientid 1

请注意,解释结果中rows字段的值也是由mysql的连接优化器粗略猜测的。请检查这个值是否与真实值基本一致。如果没有,可以通过在select语句中使用straight_join获得更好的性能,并尝试在from子句中以不同的顺序列出表。

以下是补充资料:

在explain的帮助下,您可以知道:1)当您必须索引一个表以获得使用索引查找记录的更快选择时。2)优化器是否以最佳顺序连接表。为了强制优化器对SELECT语句使用特定的连接顺序,添加了一个STRAIGHT_JOIN子句。关于解释的官方文件是在http://dev.mysql.com/doc/refman/5.1/en/using-explain.html(英语)

mysql explain详解

mysql explain 使用的方法

解释tbl_name or:解释[扩展]选择select _ options

前者可以得到一个表的字段结构等等,后者主要给出一些相关的索引信息,今天的重点是后者。

示例代码如下:mysql解释select * from事件;------| id | select _ type | table | type | possible _ keys | key | key _ len | ref | rows | Extra |----| 1 | SIMPLE | event | ALL | NULL | NULL | 13 | |-。

id查询的序列号

select_typeselect查询的类型主要是区分普通查询和联合查询、子查询等复杂查询。

表的输出行引用的表。

键入联合查询使用的类型。类型显示访问类型,这是一个重要的指标。由好到坏的结果值为:system consteq _ ref ref全文ref _ or _ null index _ merge unique _ subquery index _ subquery range index all。一般来说,需要确保查询至少达到范围级别,最好是ref级别。

Possible_keys表示MySQL可以使用哪个索引来查找这个表中的行。如果为空,则没有相关的索引。在这种情况下,为了提高性能,可以检查WHERE子句以查看是否引用了某些字段,或者检查这些字段是否不适合索引。

显示MySQL实际决定使用的密钥。如果没有选择索引,则键为空。

Key_len显示MySQL决定使用的密钥长度。如果键为空,则长度为空。注意:要特别注意这个值,以找出mysql的哪一部分实际上用在了多主键中。

显示哪个字段或常量引用与键一起使用。

Rows表示mysql需要遍历多少数据才能找到,这在innodb上是不准确的。

如果Extra是Only index,则表示只通过索引树中的信息来检索信息,比扫描整个表要快。用在哪里,就限制在哪里。如果不可能在哪里,就说明不需要在哪里。一般什么都没发现。如果该信息显示使用filesort或使用temporary,将会非常困难,并且WHERE和ORDER BY的索引不能被考虑在内。如果索引是根据WHERE确定的,那么使用filesort必然会造成ORDER BY,这就要看先筛选后排序还是先排序后筛选的性价比了。一些常见名词的解释

使用filesortMySQL需要一个额外的过程来找出如何按排序顺序检索行。

使用index检索表中的列信息,只使用索引树中的信息读取实际的行,而无需进一步搜索。

为了解决查询,MySQL需要创建一个临时表来保存结果。

Ref对于上一个表中的每个行组合,将从该表中读取具有匹配索引值的所有行。

都完全没有索引,性能很差。

与indexall相同,只是只扫描索引树。这通常比ALL快,因为索引文件通常比数据文件小。

简单选择(没有联合或子查询)

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 使用php连接mysql数据库,php连接数据库的方法
  • 使用php连接mysql数据库,php连接数据库的方法,一文详解PHP连接MySQL数据库的三种方式
  • pymysql菜鸟教程,pymysql 使用
  • pymysql菜鸟教程,pymysql 使用,pymysql模块使用简介与示例
  • mysql锁实现,mysql锁算法
  • mysql锁实现,mysql锁算法,MySQL锁机制与用法分析
  • mysql连接报错10061,mysql连接错误10060
  • mysql连接报错10061,mysql连接错误10060,MYSQL无法连接 提示10055错误的解决方法
  • mysql连接报10060错误,mysql连接报错10055
  • mysql连接报10060错误,mysql连接报错10055,MySQL连接异常报10061错误问题解决
  • mysql辅助索引和主键索引,mysql 主键 外键 索引
  • mysql辅助索引和主键索引,mysql 主键 外键 索引,MySQL索引之主键索引
  • MySQL语句大全,mysql常见语句总结
  • MySQL语句大全,mysql常见语句总结,MySQL语句整理及汇总介绍
  • mysql触发器的使用方法实验报告,mysql中触发器的使用
  • 留言与评论(共有 条评论)
       
    验证码: