操作系统:windows
EXPLAIN语句提供了一个SELECT语句的执行计划信息。
EXPLAIN返回的一行信息在SELECT语句中使用的每个表。它列出的表中的顺序是,MySQL会读他们在处理语句的输出。MySQL解决所有join使用嵌套循环连接方法。这意味着它们的MySQL读取从第一表中的一行,然后发现在第二个表匹配的行,在第三表,依此类推。当所有的表处理时,MySQL输出选中的列和通过回溯表列表直到表发现其中有更多的匹配行。下一行是从该表中读出并且该进程继续进行下一个表。
EXPLAIN返回SELECT语句中使用的每个表的一行信息。 它按照MySQL在处理语句时读取它们的顺序列出输出中的表。 MySQL使用嵌套循环连接方法解析所有连接。 这意味着MySQL从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,等等。 处理完所有表后,MySQL通过表列表输出选定的列和回溯,直到找到有更多匹配行的表。 下一行从该表中读取,并且该过程继续下一个表。
当使用EXTENDED关键字时,EXPLAIN会产生额外的信息,可以通过在EXPLAIN语句后面发出一个SHOW WARNINGS语句来查看。 EXPLAIN EXTENDED还会显示已过滤的列。
注意事项:
1.不能在同一个EXPLAIN语句中同时使用EXTENDED和PARTITIONS关键字。
1.EXPLAIN输出列
本节介绍EXPLAIN生成的输出列。 后面几节提供了有关类型和额外列的其他信息。
EXPLAIN的每个输出行提供关于一个表的信息。 每行都包含表1中汇总的值,并在表格后面详细介绍。
列
|
英文说明
|
中文说明
|
id
|
The SELECT identifier
|
SELECT标识符
|
select_type
|
The SELECT type
|
SELECT 类型
|
table
|
The table for the output row
|
表名
|
partitions
|
The matching partitions
|
匹配分区
|
type
|
The join type
|
连接类型
|
possible_keys
|
The possible indexes to choose
|
可能的索引选择
|
key
|
The index actually chosen
|
索引实际选择
|
key_len
|
The length of the chosen key
|
用到索引的长度
|
ref
|
The columns compared to the index
|
索引被用于哪一列
|
rows
|
Estimate of rows to be examined
|
预计要检查的行数
|
filtered
|
Percentage of rows filtered by table condition
|
行的百分比由过滤条件表
|
Extra
|
Additional information
|
附加信息
|
详细介绍:
1.id(SELECT标识符)
SELECT标识符。 这是查询中SELECT的连续编号。 如果行引用其他行的联合结果,则该值可以为NULL。 在这种情况下,表列显示了一个值,如
2.select_type(SELECT 类型)
SELECT的类型如下表:
select_type的值
|
英文说明
|
中文说明
|
SIMPLE
|
Simple SELECT (not using UNION or subqueries)
|
简单的SELECT(不使用UNION或子查询)
|
PRIMARY
|
Outermost SELECT
|
最外层的SELECT
|
UNION
|
Second or later SELECT statement in a UNION
|
在UNION中第二或更更后的SELECT语句
|
DEPENDENT UNION
|
Second or later SELECT statement in a UNION, dependent on outer query
|
在UNION中第二个或后面的SELECT语句,依赖于外部查询
|
UNION RESULT
|
Result of a UNION
|
UNION的结果
|
SUBQUERY
|
First SELECT in subquery
|
在子查询中的第一个SELECT
|
DEPENDENT
|
SUBQUERY First SELECT in subquery, dependent on outer query
|
在子查询中的第一个SELECT,依赖于外部查询
|
DERIVED
|
Derived table SELECT (subquery in FROM clause)
|
派生表SELECT(在FROM子句中的子查询)
|
UNCACHEABLE SUBQUERY
|
A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
|
无法缓存结果的子查询,必须对外部查询的每一行重新评估
|
UNCACHEABLE UNION
|
The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)
|
第二个或更高版本在属于不可缓存子查询的UNION中选择(请参阅UNCACHEABLE SUBQUERY)
|
DEPENDENT 通常表示使用相关的子查询。
DEPENDENTSUBQUERY评价不同于UNCACHEABLE SUBQUERY评价。对DEPENDENT SUBQUERY,子查询对于其外部上下文中的每一组不同的变量值,只重新计算一次。对于UNCACHEABLE SUBQUERY,子查询是针对外部上下文的每一行重新评估的。
子查询的可缓存性不同于查询缓存中查询结果的缓存。 在查询执行期间发生子查询缓存,而查询缓存仅在查询执行完成后用于存储结果。
3.table(表名)
输出行所引用的表的名称。 这也可以是以下值之一:
<unionM,N>
:行是指具有M和N的id值的行的联合。
<derivedN>
:行是指id值为N的行的派生表结果。例如,派生表可能来自FROM子句中的子查询。
4.partitions(匹配分区)
记录将与查询匹配的分区。 仅当使用PARTITIONS关键字时,才会显示此列。 非分区表的值为NULL。
5.type(连接类型)
连接类型。详见”EXPLAIN连接类型”部分。
6.possible_keys(可能的索引选择)
possible_keys列表示MySQL可以从中选择查找表中的行的索引。 请注意,此列完全独立于EXPLAIN输出中显示的表的顺序。 这意味着possible_keys中的一些键在实际中可能不能用于生成的表顺序。
如果这个列是NULL,那么没有相关的索引。 在这种情况下,可以通过检查WHERE子句来检查是否引用适合索引的一列或多列,从而提高查询的性能。 如果是这样,请创建一个适当的索引,并再次使用EXPLAIN检查查询。
要查看表有哪些索引,请使用
SHOW INDEX FROM tbl_name
7.key(索引实际选择)
关键字列表示MySQL实际决定使用的关键字(索引)。 如果MySQL决定使用其中一个possible_keys索引来查找行,则该索引被列为关键值。
键可能会命名不在possible_keys值中的索引。 如果任何possible_keys索引都不适合查找行,则会发生这种情况,但查询所选的所有列都是某个其他索引的列。 也就是说,指定的索引覆盖了选定的列,因此虽然不用于确定要检索的行,但索引扫描比数据行扫描更有效。
对于InnoDB,即使查询也选择主键,辅助索引可能会覆盖所选列,因为InnoDB将主键值与每个辅助索引一起存储。 如果key为NULL,则MySQL没有找到更有效执行查询的索引。
要强制MySQL使用或忽略possible_keys列中列出的索引,请在查询中使用FORCE INDEX,USE INDEX或IGNORE INDEX。
对于MyISAM和NDB表,运行ANALYZE TABLE可以帮助优化器选择更好的索引。 对于NDB表,这也提高了分布式下推连接的性能。 对于MyISAM表,myisamchk –analyze与ANALYZE TABLE的功能相同。
8.key_len(用到索引的长度)
key_len列表示MySQL决定使用的密钥的长度。 key_len的值使您能够确定MySQL实际使用的多部分密钥的多少部分。 如果键列指NULL,则len_len列也指NULL。
由于密钥的存储格式,关键字长度对于可以为NULL的列的长度大于对于NOT NULL列的关键字长度。
9.ref(索引被用于哪一列)
ref列显示哪些列或常量与键列中指定的索引进行比较,以从表中选择行。
10.rows(预计要检查的行数)
行列表示MySQL认为它必须检查以执行查询的行数。
对于InnoDB表,这个数字是一个估计,并不总是准确的。
11.filtered(行的百分比由过滤条件表)
过滤的列表示将由表条件过滤的表行的估计百分比。 也就是说,行显示了检查的估计行数,行×过滤/ 100显示了将与之前的表连接的行数。 如果使用EXPLAIN EXTENDED,则显示此列。
12.Extra(附加信息)
此列包含有关MySQL如何解析查询的其他信息。 对于不同的值的描述。
详细介绍见”EXPLAIN 输出解释”部分。
2.EXPLAIN连接类型
EXPLAIN输出的类型列描述如何连接表。 以下列表描述了从最佳类型到最差类型的连接类型:
1.system
该表只有一行(=系统表)。 这是const连接类型的特例。
2.const
该表至多有一个匹配的行,在查询开始时读取。 由于只有一行,因此该行中列的值可以被优化器的其余部分视为常量。 const表非常快,因为它们只读一次。
当将PRIMARY KEY或UNIQUE索引的所有部分与常量值进行比较时,将使用const。 在以下查询中,可以将tbl_name用作常量表:
SELECT * FROM tbl_name WHERE primary_key=1
SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2
3.eq_ref
从这个表读取一行,对于前面表格的每一行组合。 除了系统和常量类型,这是最好的连接类型。 它在索引的所有部分被连接使用并且索引是PRIMARY KEY或UNIQUE NOT NULL索引时使用。
eq_ref可用于使用=运算符进行比较的索引列。 比较值可以是一个常量,也可以是一个表达式,该表达式使用在此表之前读取的表中的列。 在以下示例中,MySQL可以使用eq_ref连接来处理ref_table:
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1
4.ref
所有具有匹配索引值的行都从这个表中读取,用于以前表中的每个行的组合。 如果连接仅使用键的最左边的前缀,或者键不是PRIMARY KEY或UNIQUE索引(换句话说,如果连接不能根据键值选择单个行),则使用ref。 如果使用的键只匹配几行,这是一个很好的连接类型。
ref可以用于使用=或<=>运算符进行比较的索引列。 在以下示例中,MySQL可以使用ref连接来处理ref_table:
SELECT * FROM ref_table WHERE key_column=expr
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1
5.fulltext
连接使用FULLTEXT索引执行。
6.ref_or_null
这种连接类型与ref类似,但是除此之外,MySQL还对包含NULL值的行进行额外的搜索。 这种连接类型优化最常用于解析子查询。 在以下示例中,MySQL可以使用ref_or_null连接来处理ref_table:
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
7.index_merge
此连接类型表示使用索引合并优化。 在这种情况下,输出行中的键列包含使用的索引列表,key_len包含所使用索引的最长键部分列表。
8.unique_subquery
这种类型替换了以下形式的一些IN子查询的eq_ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery只是一个索引查找函数,它可以完全替代子查询以提高效率。
9.index_subquery
这种连接类型与unique_subquery类似。 它取代了IN子查询,但它适用于以下形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
10.range
只有在给定范围内的行才能被检索,使用索引来选择行。 输出行中的关键列指示使用哪个索引。 key_len包含使用的最长密钥部分。 这个类型的ref列是NULL。
范围可以用于使用任何=,<>,>,> =,<,<=,IS NULL,<=>,BETWEEN或IN()运算符将键列与常量进行比较:
SELECT * FROM tbl_name
WHERE key_column = 10;
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name
WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
11.index
索引连接类型与ALL相同,只是索引树被扫描。 这发生在两个方面:
如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则只扫描索引树。 在这种情况下,额外列说使用索引。 仅索引扫描通常比ALL快,因为索引的大小通常小于表数据。
全表扫描使用索引中的读取来按索引顺序查找数据行。 使用索引不会出现在Extra列中。
当查询只使用属于单个索引一部分的列时,MySQL可以使用这种连接类型。
12.ALL
全表扫描是针对先前表中的每一行组合完成的。 如果表格是没有标记为const的第一个表格,通常情况下不好,在其他情况下通常很糟糕。 通常情况下,您可以通过添加索引来避免ALL,这些索引可以根据来自较早表的常量值或列值从表中检索行。
3.EXPLAIN 额外的信息
EXPLAIN输出的Extra列包含有关MySQL如何解析查询的附加信息。 以下列表解释了可能出现在此列中的值。 如果要尽可能快地查询,请查看使用filesort和Using temporary的额外值。
1.Child of ‘table’ pushed join@1
这个表被引用为可以下推到NDB内核的连接中的表的子表。 只适用于MySQL NDB群集7.2及更高版本,当启用了下推连接时。
2.const row not found
对于SELECT … FROM tbl_name这样的查询,表是空的。
3.Distinct
MySQL正在寻找不同的值,所以当它找到第一个匹配的行后,它停止为当前行组合搜索更多的行。
4.Full scan on NULL key
当优化程序不能使用索引查找访问方法时,会发生子查询优化作为回退策略。
5.Impossible HAVING
HAVING子句总是为false,不能选择任何行。
6.Impossible WHERE
WHERE子句总是为false,不能选择任何行。
7.Impossible WHERE noticed after reading const tables
MySQL已经读取了所有的const(和system)表,并注意到WHERE子句总是为false。
8.No matching min/max row
没有行满足查询的条件,如SELECT MIN(…)FROM … WHERE条件。
9.no matching row in const table
对于具有连接的查询,有一个空表或一个没有满足唯一索引条件的行的表。
10.No tables used
查询没有FROM子句,或者有FROM DUAL子句。
11.Not exists
MySQL能够对查询执行LEFT JOIN优化,并且在找到与LEFT JOIN条件相匹配的一行之后,不会在该表中检查前一行组合的更多行。 以下是可以用这种方式进行优化的查询类型的示例:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id
WHERE t2.id IS NULL;
假定t2.id被定义为NOT NULL。 在这种情况下,MySQL扫描t1并使用t1.id的值查找t2中的行。 如果MySQL在t2中找到匹配的行,它就知道t2.id不能为NULL,并且不会扫描t2中具有相同id值的其余行。 换句话说,对于t1中的每一行,MySQL只需要在t2中进行一次查找,而不管在t2中实际匹配了多少行。
12.Range checked for each record (index map: N)
MySQL发现没有好的索引使用,但发现一些索引可能在前面表格的列值已知之后使用。 对于上表中的每一行组合,MySQL检查是否可以使用range或index_merge访问方法来检索行。 这不是很快,但是比完全没有索引的连接要快。 适用性标准如“范围优化”和“索引合并优化”中所述,不同之处在于前表的所有列值是已知的并被认为是常数。
索引从1开始编号,其顺序与表中SHOW INDEX所示的顺序相同。 索引映射值N是指示哪些索引是候选的位掩码值。 例如,值0x19(二进制11001)意味着将考虑索引1,4和5。
13.Scanned N databases
这表示在处理对INFORMATION_SCHEMA表的查询时,服务器执行多少个目录扫描,如“优化INFORMATION_SCHEMA查询”中所述。 N的值可以是0,1或全部。
14.Select tables optimized away
优化器确定1)至多应该返回一行,并且2)为了产生该行,必须读取一组确定的行。 当在优化阶段读取的行可以被读取(例如通过读取索引行)时,在查询执行期间不需要读取任何表。
当查询被隐式分组(包含一个聚合函数但没有GROUP BY子句)时,满足第一个条件。 当使用每个索引执行一个行查找时,满足第二个条件。 读取的索引数决定了要读取的行数。
考虑下面的隐式分组查询:
SELECT MIN(c1), MIN(c2) FROM t1;
假设MIN(c1)可以通过读取一个索引行来获取,而MIN(c2)可以通过从不同索引读取一行来获取。 也就是说,对于每个列c1和c2,存在索引,其中列是索引的第一列。 在这种情况下,返回一行,通过读取两个确定性行产生。
如果要读取的行不是确定性的,则不会出现此额外值。 考虑这个查询:
SELECT MIN(c2) FROM t1 WHERE c1 <= 10;
假设MIN(c1)可以通过读取一个索引行来获取,而MIN(c2)可以通过从不同索引读取一行来获取。 也就是说,对于每个列c1和c2,存在索引,其中列是索引的第一列。 在这种情况下,返回一行,通过读取两个确定性行产生。
如果要读取的行不是确定性的,则不会出现此额外值。 考虑这个查询:
SELECT MIN(c2) FROM t1 WHERE c1 <= 10;
假设(c1,c2)是覆盖索引。 使用此索引,必须扫描c1 <= 10的所有行以查找最小c2值。 相比之下,考虑这个查询:
SELECT MIN(c2) FROM t1 WHERE c1 = 10;
在这种情况下,c1 = 10的第一个索引行包含最小的c2值。 只有一行必须被读取以产生返回的行。
对于每个表(例如MyISAM,而不是InnoDB)保持精确行计数的存储引擎,对于WHERE子句缺失或始终为真且没有GROUP BY子句的COUNT(*)查询,可能会发生此额外值。 (这是隐式分组查询的一个实例,存储引擎影响是否可读取确定数量的行。
15.Skip_open_table, Open_frm_only, Open_full_table
这些值表示适用于对INFORMATION_SCHEMA表的查询的文件打开优化
*Skip_open_table:表格文件不需要打开。 通过扫描数据库目录,查询内的信息已经可用。
*Open_frm_only:只有表格的.frm文件需要打开。
*Open_full_table:未优化的信息查询。 .frm,.MYD和.MYI文件必须打开。
16.unique row not found
对于像SELECT … FROM tbl_name这样的查询,没有行满足表中UNIQUE索引或PRIMARY KEY的条件。
17.Using filesort
MySQL必须做一个额外的传递才能找出如何按排序顺序检索行。 排序是通过根据连接类型遍历所有行并存储与WHERE子句匹配的所有行的排序键和指向行的指针来完成的。 然后对键进行排序,并按排序顺序检索行。
18.Using index
只使用索引树中的信息从表中检索列信息,而不必执行额外的查找来读取实际的行。 当查询仅使用属于单个索引一部分的列时,可以使用此策略。
对于具有用户定义的聚簇索引的InnoDB表,即使Extra列中不存在使用索引,也可以使用该索引。 如果type是索引而key是PRIMARY,则是这种情况。
19.Using index for group-by
与使用索引表访问方法类似,对group-by使用index指示MySQL找到了一个索引,可用于检索GROUP BY或DISTINCT查询的所有列,而无需对实际表进行任何额外的磁盘访问。 此外,索引以最有效的方式使用,因此对于每个组,只有少数索引条目被读取。
20.Using join buffer
先前连接的表被分成几部分读入连接缓冲区,然后从缓冲区中使用它们的行来执行与当前表的连接。
21.Using sort_union(…), Using union(…), Using intersect(…)
这些表明特定的算法显示索引扫描如何合并index_merge连接类型。
22.Using temporary
为了解决这个查询,MySQL需要创建一个临时表来保存结果。 如果查询包含以不同方式列出列的GROUP BY和ORDER BY子句,则通常会发生这种情况。
23.Using where
WHERE子句用于限制哪些行与下一个表匹配或发送给客户端。 除非您专门打算从表中读取或检查所有行,否则如果Extra值不是使用Where和表连接类型是ALL或索引,则查询中可能有问题。 即使您对WHERE子句的所有部分使用索引,也可能会看到如果列可以为NULL,则使用where。
24.Using where with pushed condition
此项目仅适用于NDB表格。 这意味着NDB集群正在使用条件下推优化来提高直接比较非索引列和常量的效率。 在这种情况下,条件被“推下”到集群的数据节点,并在所有数据节点上同时进行评估。 这消除了通过网络发送不匹配的行的需要,并且在情况下推可能但不被使用的情况下,可以将这些查询加速5到10倍。
4.EXPLAIN 输出解释
您可以通过使用EXPLAIN输出的rows列中的值的乘积来很好地指示连接有多好。 这应该大致告诉你MySQL必须检查多少行来执行查询。 如果使用max_join_size系统变量限制查询,则该行产品还用于确定要执行哪个多表SELECT语句以及要中止哪个。
以下示例显示了如何根据EXPLAIN提供的信息逐步优化多表连接。
假设你有这里显示的SELECT语句,并且你打算使用EXPLAIN来检查它:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
tt.ProjectReference, tt.EstimatedShipDate,
tt.ActualShipDate, tt.ClientID,
tt.ServiceCodes, tt.RepetitiveID,
tt.CurrentProcess, tt.CurrentDPPerson,
tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
et_1.COUNTRY, do.CUSTNAME
FROM tt, et, et AS et_1, do
WHERE tt.SubmitTime IS NULL
AND tt.ActualPC = et.EMPLOYID
AND tt.AssignedPC = et_1.EMPLOYID
AND tt.ClientID = do.CUSTNMBR;
对于这个例子,做出以下假设:
被比较的列已经被宣布如下:
表 | 列 | 数据类型 |
---|
tt | ActualPC | CHAR(10) |
tt | AssignedPC | CHAR(10) |
tt | ClientID | CHAR(10) |
et | EMPLOYID | CHAR(15) |
do | CUSTNMBR | CHAR(15) |
这些表具有以下索引:
表 | 索引 |
---|
tt | ActualPC |
tt | AssignedPC |
tt | ClientID |
et | EMPLOYID (primary key) |
do | CUSTNMBR (primary key) |
tt.ActualPC值不是均匀分布的
最初,在执行任何优化之前,EXPLAIN语句会生成以下信息:
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
do ALL PRIMARY NULL NULL NULL 2135
et_1 ALL PRIMARY NULL NULL NULL 74
tt ALL AssignedPC, NULL NULL NULL 3872
ClientID,
ActualPC
Range checked for each record (index map: 0x23)
因为每个表的类型都是ALL,所以这个输出表明MySQL正在生成所有表的笛卡尔积; 也就是每行的组合。 这需要相当长的时间,因为必须检查每个表中行数的乘积。 对于手头的情况,本产品为74×2135×74×3872 = 45,268,558,720行。 如果桌子更大,你只能想象需要多长时间。
这里的一个问题是,如果MySQL声明为相同的类型和大小,MySQL可以更有效地在列上使用索引。 在这种情况下,如果将VARCHAR和CHAR声明为相同的大小,则认为它们是相同的。 tt.ActualPC被声明为CHAR(10),而et.EMPLOYID是CHAR(15),因此存在长度不匹配。
要修复列长度之间的差异,请使用ALTER TABLE将ActualPC从10个字符扩展到15个字符:
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
现在tt.ActualPC和et.EMPLOYID都是VARCHAR(15)。 再次执行EXPLAIN语句会产生这样的结果:
table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC, NULL NULL NULL 3872 Using
ClientID, where
ActualPC
do ALL PRIMARY NULL NULL NULL 2135
Range checked for each record (index map: 0x1)
et_1 ALL PRIMARY NULL NULL NULL 74
Range checked for each record (index map: 0x1)
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
这并不完美,但要好得多:行值的乘积减少了74倍。该版本在几秒钟内执行。
第二个改变可以消除tt.AssignedPC = et_1.EMPLOYID和tt.ClientID = do.CUSTNMBR比较的列长度不匹配:
mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
MODIFY ClientID VARCHAR(15);
修改之后,EXPLAIN生成如下所示的输出:
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using
ClientID, where
ActualPC
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
在这一点上,查询几乎尽可能地优化。 剩下的问题是,默认情况下,MySQL假设tt.ActualPC列中的值是均匀分布的,tt表不是这种情况。 幸运的是,很容易告诉MySQL分析密钥分配:
mysql> ANALYZE TABLE tt;
有了额外的索引信息,连接是完美的,EXPLAIN产生这样的结果:
table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC NULL NULL NULL 3872 Using
ClientID, where
ActualPC
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
EXPLAIN输出中的rows列是来自MySQL连接优化器的有根据的猜测。 通过将行产品与查询返回的实际行数进行比较来检查数字是否接近真相。 如果数字非常不同,则可以在SELECT语句中使用STRAIGHT_JOIN并尝试在FROM子句中以不同的顺序列出表。
当在子查询中使用EXPLAIN SELECT时,可能会在某些情况下执行修改数据的语句
Reference:
dev.mysql.com/doc/refman/…
dev.mysql.com/doc/workben…
如需转载请标明出处
QQ技术交流群:129518033