10bet网址
MySQL 5.7参考手册
相关的文档10bet官方网站 下载本手册
PDF(美国高级主任)- 36.3 mb
PDF (A4)- 36.3 mb
手册页(TGZ)- 235.4 kb
手册页(Zip)- 347.1 kb
信息(Gzip)- 3.3 mb
信息(邮政编码)- 3.3 mb
本手册节选

8.8.2 EXPLAIN输出格式

解释statement提供MySQL如何执行语句的信息。解释适用于选择删除插入取代,更新语句。

解释类中使用的每个表返回一行信息选择声明。它按照MySQL在处理语句时读取表的顺序列出了输出中的表。MySQL使用嵌套循环连接方法解析所有连接。这意味着MySQL从第一个表中读取一行,然后在第二个表、第三个表中查找匹配的行,以此类推。处理完所有表后,MySQL输出所选的列,并通过表列表进行回溯,直到找到有更多匹配行的表。从该表中读取下一行,然后继续处理下一个表。

解释输出包括分区信息。同时,为选择语句,解释生成可以显示的扩展信息显示警告后,解释(见第8.8.3节,“扩展EXPLAIN输出格式”).

请注意

在旧的MySQL版本中,分区和扩展信息是使用解释分区而且解释扩展.这些语法仍然可以被识别为向后兼容性,但分区和扩展输出现在默认启用,因此分区而且扩展关键字是多余的,不推荐使用。使用它们会导致警告;期望他们从解释语法,在未来的MySQL版本。

不能使用已弃用的分区而且扩展关键词在一起是一样的解释声明。此外,这两个关键字都不能与格式选择。

请注意

MySQL工作台有一个可视化解释功能,它提供了一个可视化的表示解释输出。看到教程:使用Explain提高查询性能

解释输出列

的输出列解释.属性的附加信息类型而且额外的列。

的每个输出行解释提供关于一个表的信息。中总结的值表8.1,“EXPLAIN输出列”,并在下表中详细描述。列名显示在表的第一列中;第二列提供输出中显示的等效属性名= JSON格式使用。

表8.1 EXPLAIN输出列

JSON的名字 意义
id select_id 选择标识符
select_type 没有一个 选择类型
表格 table_name 输出行的表
分区 分区 匹配的分区
类型 access_type 连接类型
possible_keys possible_keys 要选择的可能索引
关键 关键 实际选择的索引
key_len key_length 所选键的长度
裁判 裁判 列与索引的比较
估计要检查的行数
过滤后的 过滤后的 按表条件筛选的行百分比
额外的 没有一个 额外的信息

请注意

JSON属性不显示在json格式解释输出。

  • id(JSON的名字:select_id

    选择标识符。这是选择在查询中。取值为如果行指向其他行的并集结果。在这种情况下,表格列显示如下的值<联盟N>表示行的并集id的值而且N

  • select_type(JSON名称:none)

    的类型选择,可以是下表中所示的任何一个。一个json格式的解释暴露了选择类型的属性query_block,除非是简单的主要的.JSON名称(如果适用)也显示在表中。

    select_type价值 JSON的名字 意义
    简单的 没有一个 简单的选择(不使用联盟或子查询)
    主要的 没有一个 最外层选择
    联盟 没有一个 第二或更高选择中的语句联盟
    依赖联盟 依赖真正的 第二或更高选择中的语句联盟,依赖于外部查询
    联盟的结果 union_result 的结果联盟
    子查询 没有一个 第一个选择在子查询
    相关子查询 依赖真正的 第一个选择在子查询中,依赖于外部查询
    派生的 没有一个 派生表
    物化 materialized_from_subquery 物化子查询
    当前子查询 缓存 一个子查询,其结果不能被缓存,必须为外部查询的每一行重新计算
    各种联盟 缓存 中的第二个或后面的选择联盟它属于一个不可缓存的子查询(参见当前子查询

    依赖通常表示使用相关的子查询。看到13.2.10.7节,“相关子查询”

    相关子查询评价不同于当前子查询评估。为相关子查询时,子查询只对来自外部上下文的每一组变量的不同值重新求值一次。为当前子查询,子查询将为外层上下文的每一行重新计算。

    子查询的可缓存性不同于查询缓存中的查询结果缓存(在章节8.10.3.1,“查询缓存如何运行”).子查询缓存发生在查询执行期间,而查询缓存仅用于在查询执行完成后存储结果。

    当你指定= JSON格式解释时,输出没有一个直接等价的属性select_type;的query_block属性对应于给定的选择.属性相当于大部分的选择刚才显示的子查询类型是可用的(例如materialized_from_subquery物化),并在适当时显示。没有等价的JSON简单的主要的

    select_type非-选择Statements显示受影响表的语句类型。例如,select_type删除删除语句。

  • 表格(JSON的名字:table_name

    输出行所引用的表的名称。它也可以是以下值之一:

    • <联盟N>:行表示与的行并集id的值而且N

    • <派生N>:该行引用具有id的价值N.类中的子查询可以生成派生表条款。

    • <子查询N>属性行的实体化子查询结果id的价值N.看到第8.2.2.2节,“用物化优化子查询”

  • 分区(JSON的名字:分区

    查询将从中匹配记录的分区。取值为对于非分区表。看到第22.3.5节“获取分区信息”

  • 类型(JSON的名字:access_type

    连接类型。有关不同类型的描述,请参见解释连接类型

  • possible_keys(JSON的名字:possible_keys

    possible_keyscolumn表示MySQL可以从中选择查找该表中的行的索引。注意,该列与输出中显示的表的顺序完全无关解释.这意味着一些关键possible_keys可能无法在实际中使用生成的表顺序。

    如果这一列是(或者在json格式的输出中未定义),没有相关的索引。方法可以提高查询的性能在哪里子句,以检查它是否引用某个或多个适合建立索引的列。如果是,则创建适当的索引并使用解释再一次。看到第13.1.8节“ALTER TABLE语句”

    要查看表有哪些索引,请使用显示索引来自tbl_name

  • 关键(JSON的名字:关键

    关键列表示MySQL实际决定使用的键(索引)。如果MySQL决定使用possible_keys索引查找行,该索引被列为键值。

    这是可能的关键类中不存在的索引的名称possible_keys价值。如果没有possible_keys索引适用于查找行,但是查询所选择的所有列都是其他索引的列。也就是说,命名索引覆盖选定的列,因此尽管不使用它来确定检索哪些行,但索引扫描比数据行扫描更有效。

    InnoDB,即使查询还选择主键,辅助索引也可能覆盖所选列,因为InnoDB用每个辅助索引存储主键值。如果关键, MySQL发现没有索引可以更有效地执行查询。

    中列出的索引,强制MySQL使用或忽略possible_keys列,使用力指数使用索引,或忽略指数在您的查询中。看到第8.9.4节“索引提示”

    MyISAM表、运行分析表帮助优化器选择更好的索引。为MyISAM表,myisamchk——分析也一样。看到13.7.2.1节“ANALYZE TABLE语句”,第7.6节,“MyISAM表维护和崩溃恢复”

  • key_len(JSON的名字:key_length

    key_len列表示MySQL决定使用的键的长度。的价值key_len使您可以确定MySQL实际使用的多部分键的多少部分。如果关键列表示,key_len列还说

    由于键存储格式的原因,对于可以为的列,键长度要大1而不是非空列。

  • 裁判(JSON的名字:裁判

    裁判类中指定的索引与哪些列或常量进行比较关键列从表中选择行。

    如果值为函数,所使用的值是某个函数的结果。要查看哪个函数,请使用显示警告解释为了看到延伸的解释输出。函数实际上可能是一个运算符,例如算术运算符。

  • (JSON的名字:

    column表示MySQL认为执行查询必须检查的行数。

    InnoDB表,这个数字是一个估计,并不总是准确的。

  • 过滤后的(JSON的名字:过滤后的

    过滤后的列指示由表条件过滤的表行的估计百分比。最大值为100,这意味着没有发生行过滤。从100开始递减的值表示过滤量的增加。显示检查和的估计行数×过滤后的显示与下表连接的行数。例如,如果是1000和过滤后的为50.00(50%),则与下表连接的行数为1000 × 50% = 500。

  • 额外的(JSON名称:none)

    本列包含关于MySQL如何解析查询的附加信息。有关不同值的说明,请参见解释额外的信息

    属性对应的JSON属性不存在额外的列;对象的文本或JSON属性公开此列中可能出现的值消息财产。

解释连接类型

类型列的解释输出描述了表是如何连接的。的值在json格式的输出中找到access_type财产。下面的列表描述了连接类型,从最好的类型到最差的:

  • 系统

    该表只有一行(= system表)。这是一个特例常量连接类型。

  • 常量

    该表最多有一个匹配行,在查询开始时读取。因为只有一行,这一行中的列的值可以被优化器的其余部分视为常量。常量表非常快,因为它们只被读取一次。

    常量比较语句的所有部分时使用主键独特的索引到常数值。在以下查询中,tbl_name可以用作常量表:

    Select * fromtbl_name在哪里primary_key= 1;Select * fromtbl_name在哪里primary_key_part1= 1,primary_key_part2= 2;
  • eq_ref

    对于前几个表中的每个行组合,从该表中读取一行。除了系统而且常量类型,这是最好的连接类型。当连接使用索引的所有部分并且索引为主键唯一的非空索引。

    eq_ref可以用于使用?方法进行比较的索引列操作符。比较值可以是一个常量,也可以是一个表达式,该表达式使用在此表之前读取的表中的列。在下面的例子中,MySQL可以使用eq_ref加入流程ref_table

    Select * fromref_tableother_table在哪里ref_tablekey_columnother_table;Select * fromref_tableother_table在哪里ref_tablekey_column_part1other_tableref_tablekey_column_part2= 1;
  • 裁判

    对于前几个表中的每个行组合,从该表中读取具有匹配索引值的所有行。裁判如果连接仅使用键的最左边的前缀,或者如果键不是主键独特的索引(换句话说,如果联接不能基于键值选择单行)。如果所使用的键只匹配几行,则这是一个很好的连接类型。

    裁判可以用于使用?方法进行比较的索引列< = >操作符。在下面的例子中,MySQL可以使用裁判加入流程ref_table

    Select * fromref_table在哪里key_columnexpr;Select * fromref_tableother_table在哪里ref_tablekey_columnother_table;Select * fromref_tableother_table在哪里ref_tablekey_column_part1other_tableref_tablekey_column_part2= 1;
  • 全文

    连接使用全文索引。

  • ref_or_null

    这种连接类型类似于裁判,但是MySQL会额外搜索包含值。这种连接类型优化最常用于解析子查询。在下面的例子中,MySQL可以使用ref_or_null加入流程ref_table

    Select * fromref_table在哪里key_columnexprkey_column是零;

    看到第8.2.1.13节“IS NULL优化”

  • index_merge

    此连接类型表示使用索引合并优化。在这种情况下,关键列中包含使用的索引列表,和key_len包含所使用索引的最长键部分的列表。有关更多信息,请参见章节8.2.1.3,“索引合并优化”

  • unique_subquery

    此类型替换eq_ref对于一些以下形式的子查询:

    价值(选择primary_keysingle_table在哪里some_expr

    unique_subquery只是一个索引查找函数,完全替换子查询以提高效率。

  • index_subquery

    此连接类型类似于unique_subquery.它取代子查询,但它适用于以下形式的子查询中的非唯一索引:

    价值(选择key_columnsingle_table在哪里some_expr
  • 范围

    只检索给定范围内的行,使用索引选择行。的关键输出行的列指示使用哪个索引。的key_len包含所使用的最长的键部分。的裁判列是对于这种类型。

    范围将键列与常量进行比较时,可以使用<>>> =<< =为空< = >之间的就像,或在()运营商:

    Select * fromtbl_name在哪里key_column= 10;Select * fromtbl_name在哪里key_column10到20之间;Select * fromtbl_name在哪里key_column在(10年,20年,30);Select * fromtbl_name在哪里key_part1= 10 andkey_part2在(10年,20年,30);
  • 指数

    指数连接类型与所有,除了扫描索引树。这有两种方式:

    • 如果索引是查询的覆盖索引,并且可以用于满足表中所需的所有数据,则只扫描索引树。在这种情况下,额外的列表示使用索引.仅索引扫描通常比所有因为索引的大小通常小于表数据。

    • 使用从索引中读取数据来按索引顺序查找数据行,执行全表扫描。使用索引不出现在额外的列。

    当查询只使用作为单个索引一部分的列时,MySQL可以使用这种连接类型。

  • 所有

    对前一个表中的每个行组合执行全表扫描。如果表是第一个没有标记的表,这通常是不好的常量,通常非常其他情况都不好。通常情况下,你可以避免所有通过添加索引,支持基于常量值或早期表中的列值从表中检索行。

解释额外信息

额外的列的解释输出包含MySQL如何解析查询的附加信息。下面的列表说明了可以出现在此列中的值。每个项还指示对于json格式的输出,哪个属性显示额外的价值。对于其中一些,有一个特定的性质。的文本显示消息财产。

如果您想使您的查询尽可能快,请注意额外的的列值使用filesort而且使用临时,或者json格式的解释输出,using_filesort而且using_temporary_table属性等于真正的

  • '的孩子表格推送join@1(JSON:消息文本)

    的子表引用表格在一个可以下推到NDB内核的连接中。仅适用于NDB集群,当下推连接启用时。的描述ndb_join_pushdown服务器系统变量获取更多信息和示例。

  • 未找到Const行(JSON属性:const_row_not_found

    对于查询,例如选择……从tbl_name当我离开时,桌子是空的。

  • 删除所有行(JSON属性:消息

    删除,一些存储引擎(如MyISAM)支持一个处理程序方法,以简单和快速的方式删除所有表行。这额外的如果引擎使用此优化,则显示。

  • 截然不同的(JSON属性:截然不同的

    MySQL正在寻找不同的值,因此在找到第一个匹配的行之后,它会停止为当前行组合搜索更多的行。

  • FirstMatch (tbl_name(JSON属性:first_match

    半连接FirstMatch连接捷径策略用于tbl_name

  • 对NULL键进行完整扫描(JSON属性:消息

    当优化器不能使用索引查找访问方法时,子查询优化作为一种回退策略会出现这种情况。

  • 不可能有(JSON属性:消息

    子句总是false,不能选择任何行。

  • 不可能的,(JSON属性:消息

    在哪里子句总是false,不能选择任何行。

  • 不可能在读取const表后注意到WHERE(JSON属性:消息

    MySQL已经读取所有常量(和系统)表,并注意在哪里子句总是假的。

  • LooseScan (..n(JSON属性:消息

    使用半连接LooseScan策略。而且n是关键零件号。

  • 没有匹配的最小/最大行(JSON属性:消息

    没有行满足查询的条件,例如选择最小值(…)从…在哪里条件

  • const表中没有匹配的行(JSON属性:消息

    对于具有连接的查询,存在一个空表或一个表中没有满足唯一索引条件的行。

  • 分区修剪后没有匹配的行(JSON属性:消息

    删除更新,优化器在分区修剪后没有发现任何要删除或更新的内容。它在意思上与…相似不可能的,选择语句。

  • 没有使用表(JSON属性:消息

    查询没有从句,或有从双条款。

    插入取代语句,解释当没有时显示此值选择部分。例如,它出现在解释INSERT INTO t VALUES(10)因为它等于解释插入t从对偶中选择10

  • 不存在(JSON属性:消息

    MySQL能够做一个左连接查询上的优化,并且在找到与上一个行组合匹配的行后,不检查此表中的更多行左连接标准。下面是一个可以这样优化的查询类型的例子:

    SELECT * FROM t1左连接t2在t1.id=t2。id WHERE t2。id为NULL;

    假设t2.id定义为非空.在这种情况下,MySQL进行扫描t1然后查找里面的行t2使用的值t1.id.如果MySQL在中找到匹配的行t2,它知道t2.id永远不可能,并且不扫描其余的行t2都是一样的id价值。换句话说,对于每一行t1, MySQL只需要做一个查找t2,不管实际匹配了多少行t2

  • 计划还没准备好(JSON属性:none)

    此值出现在连接说明当优化器尚未为在命名连接中执行的语句创建执行计划时。如果执行计划输出包含多行,则其中任何一行或所有一行都可能具有此属性额外的值,这取决于优化器在确定完整执行计划时的进度。

  • 为每个记录检查的范围(索引映射:N(JSON属性:消息

    MySQL发现没有好的索引可以使用,但发现在前面表中的列值已知后,可以使用一些索引。对于上述表中的每个行组合,MySQL检查是否可以使用范围index_mergeAccess方法来检索行。这不是很快,但比执行没有索引的连接要快。适用性标准见第8.2.1.2节,“范围优化”,章节8.2.1.3,“索引合并优化”,除了上表的所有列值都是已知的,并被认为是常量。

    索引从1开始编号,顺序与显示指数在桌子上。索引映射值N位掩码值,指示哪些索引是候选索引。例如,值0 x19(binary 11001)表示考虑索引1、4和5。

  • 扫描N数据库(JSON属性:消息

    这表示服务器在处理查询时执行多少目录扫描INFORMATION_SCHEMA表,如章节8.2.3,“优化INFORMATION_SCHEMA查询”.的价值N可以是0、1或所有

  • 选择优化后的表(JSON属性:消息

    优化器确定1)最多应该返回一行,2)为了生成这一行,必须读取一组确定的行。如果在优化阶段可以读取要读取的行(例如,通过读取索引行),则在查询执行期间不需要读取任何表。

    当查询隐式分组(包含一个聚合函数,但没有集团条款)。当对使用的每个索引执行一行查找时,第二个条件就满足了。读取索引的数量决定了要读取的行数。

    考虑以下隐式分组查询:

    SELECT MIN(c1), MIN(c2) FROM t1;

    假设分钟(c1)可以通过读取一个索引行和分钟(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),这额外的值可以发生在COUNT (*)的查询在哪里子句缺失或总是真,没有集团条款。(这是一个隐式分组查询的实例,其中存储引擎会影响是否可以读取确定数量的行。)

  • Skip_open_tableOpen_frm_onlyOpen_full_table(JSON属性:消息

    这些值指示应用于查询的文件打开优化INFORMATION_SCHEMA表,如章节8.2.3,“优化INFORMATION_SCHEMA查询”

    • Skip_open_table:表文件不需要打开。通过扫描数据库目录,查询中的信息已经可用。

    • Open_frm_only只有桌子的.frm文件需要打开。

    • Open_full_table:未优化信息查找。的.frm.MYD,.MYI文件必须打开。

  • 开始临时暂时的结束(JSON属性:消息

    这表明半连接副本清除策略使用临时表。

  • 未找到唯一行(JSON属性:消息

    对于查询,例如选择……从tbl_name,没有行满足a的条件独特的索引或主键在桌子上。

  • 使用filesort(JSON属性:using_filesort

    MySQL必须执行额外的操作,以找出如何按顺序检索行。对象的连接类型遍历所有行,并为匹配的所有行存储排序键和指向该行的指针在哪里条款。然后对键进行排序,并按排序顺序检索行。看到第8.2.1.14节,“优化排序”

  • 使用索引(JSON属性:using_index

    只使用索引树中的信息从表中检索列信息,而不需要执行额外的查找操作来读取实际行。当查询仅使用作为单个索引一部分的列时,可以使用此策略。

    InnoDB具有用户定义的聚集索引的表,即使在以下情况下也可以使用该索引使用索引缺席了额外的列。这是如果的情况类型指数而且关键主要的

  • 使用索引条件(JSON属性:using_index_condition

    读取表的方法是访问索引元组并首先测试它们,以确定是否读取完整的表行。通过这种方式,索引信息被用于延迟(下推)读取完整的表行,除非有必要。看到章节8.2.1.5,“索引条件下推优化”

  • 使用index进行分组(JSON属性:using_index_for_group_by

    类似于使用索引表访问方法,使用index进行分组表示MySQL找到了一个索引,可以用来检索a的所有列集团截然不同的查询时不需要对实际表进行任何额外的磁盘访问。此外,以最有效的方式使用索引,因此对于每个组,只读取少数索引项。详细信息请参见第8.2.1.15节,“优化分组”

  • 使用连接缓冲区(块嵌套循环)使用连接缓冲区(批量密钥访问)(JSON属性:using_join_buffer

    早期连接中的表部分读入连接缓冲区,然后从缓冲区中使用它们的行来执行与当前表的连接。(块嵌套循环)表示使用块嵌套循环算法和(匙匙批接)表示使用批量密钥访问算法。的前一行表中的键解释输出被缓冲,匹配的行从表中批量提取使用连接缓冲区出现了。

    在json格式输出中,的值using_join_buffer总是其中之一吗块嵌套循环批量密钥访问

    有关这些算法的详细信息,请参见块嵌套循环连接算法,批处理键访问连接

  • 使用MRR(JSON属性:消息

    使用Multi-Range read优化策略读取表。看到第8.2.1.10节“多范围读优化”

  • 使用sort_union(…)使用联盟(…)使用相交(…)(JSON属性:消息

    属性的索引扫描合并的特定算法index_merge连接类型。看到章节8.2.1.3,“索引合并优化”

  • 使用临时(JSON属性:using_temporary_table

    要解析查询,MySQL需要创建一个临时表来保存结果。如果查询包含集团而且命令以不同方式列出列的子句。

  • 使用在哪里(JSON属性:attached_condition

    一个在哪里子句用于限制哪些行与下一个表匹配或发送到客户端。方法获取或检查表中的所有行,否则查询中可能出现错误额外的价值不是使用在哪里表连接类型为所有指数

    使用在哪里在json格式的输出中没有直接对应的内容;的attached_condition属性包含在哪里使用条件。

  • 使用where和push条件(JSON属性:消息

    本条款适用于NDB只有.这意味着NDB集群正在使用条件下推优化来提高非索引列和常量之间直接比较的效率。在这种情况下,条件是下推发送到集群的数据节点,并在所有数据节点上同时计算。这样就不需要通过网络发送不匹配的行,并且可以将这种查询速度提高5到10倍,而不是使用Condition Pushdown。有关更多信息,请参见章节8.2.1.4“发动机状态下压优化”

  • 零极限(JSON属性:消息

    这个问题有一个极限0子句且不能选择任何行。

输出解释

方法中的值的乘积可以很好地指示一个连接有多好的列解释输出。这将大致告诉您MySQL必须检查多少行才能执行查询。方法限制查询max_join_size系统变量,这个行积也是用来确定哪个多表的选择要执行的语句和要中止的语句。看到第5.1.1节“配置服务器”

下面的示例显示如何根据所提供的信息逐步优化多表连接解释

假设你有选择语句,您计划使用它进行检查解释

解释选择tt。TicketNumber, tt。TimeIn, tt。ProjectReference, tt。EstimatedShipDate, tt。ActualShipDate, tt。ClientID, tt。ServiceCodes, tt。RepetitiveID, tt。CurrentProcess, tt。CurrentDPPerson, tt。RecordVolume, tt。dpprint, et.COUNTRY, et_1。国家,做。CUSTNAME FROM tt, et, et AS et_1, do WHERE tt。提交时间是NULL和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)
    EMPLOYID CHAR (15)
    CUSTNMBR CHAR (15)
  • 这些表有以下索引。

    表格 指数
    tt ActualPC
    tt AssignedPC
    tt ClientID
    EMPLOYID(主键)
    CUSTNMBR(主键)
  • tt。一个ctualPC数值分布并不均匀。

最初,在执行任何优化之前解释语句产生以下信息:

表类型possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL NULL 74 tt ALL AssignedPC, NULL NULL NULL NULL 3872 ClientID, ActualPC范围检查每条记录(索引映射:0x23)

因为类型所有对于每个表,这个输出表明MySQL正在生成所有表的笛卡尔积;也就是说,每一行的组合。这需要相当长的时间,因为必须检查每个表中行数的乘积。对于手头的例子,这个乘积是74 × 2135 × 74 × 3872 = 45,268,558,720行。如果桌子再大一些,你可以想象需要多长时间。

这里的一个问题是,如果将列声明为相同的类型和大小,MySQL可以更有效地使用列上的索引。在这种情况下,VARCHAR而且字符如果它们声明为相同的大小,则被认为是相同的。tt。一个ctualPC声明为CHAR (10)而且et.EMPLOYIDCHAR (15),所以长度不匹配。

若要修复列长度之间的差异,请使用ALTER TABLE延长ActualPC10 ~ 15个字符:

mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR

现在tt。一个ctualPC而且et.EMPLOYID都是VARCHAR (15).执行解释语句再次产生如下结果:

table type possible_keys key key_len ref rows Extra tt ALL AssignedPC, NULL NULL NULL NULL 3872 Using ClientID, where ActualPC do ALL PRIMARY NULL NULL NULL 2135检查每条记录的范围(索引映射:0x1) et_1 ALL PRIMARY NULL NULL NULL 74检查每条记录的范围(索引映射:0x1) et eq_ref PRIMARY PRIMARY 15 tt。ActualPC 1

这不是完美的,但要好得多:的产品值是74的1 / 4。这个版本在几秒钟内执行。

属性的列长度不匹配,可以进行第二种更改tt。一个ssignedPC = et_1.EMPLOYID而且tt。ClientID = do。CUSTNMBR比较:

mysql> ALTER TABLE tt MODIFY assigndpc VARCHAR(15),修改客户端VARCHAR(15);

在修改之后,解释产生如下所示的输出:

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。assign dpc 1 do eq_ref PRIMARY PRIMARY 15 tt。ClientID 1

此时,查询几乎得到了尽可能好的优化。剩下的问题是,默认情况下,MySQL假设tt。一个ctualPC列是均匀分布的,而对列则不是这样tt表格幸运的是,告诉MySQL分析密钥分布是很容易的:

mysql>分析表tt;

有了附加的索引信息,连接就完美了解释产生如下结果:

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。assign dpc 1 do eq_ref PRIMARY PRIMARY 15 tt。ClientID 1

列中的解释是MySQL连接优化器的一个有根据的猜测。检查数字是否接近事实,通过比较与查询返回的实际行数的乘积。如果数字相差很大,则可以使用STRAIGHT_JOIN在你的选择语句中以不同的顺序列出表条款。(然而,STRAIGHT_JOIN可能阻止使用索引,因为它禁用半连接转换。看到8.2.2.1节,“使用半连接转换优化子查询、派生表和视图引用”.)

在某些情况下,可以执行修改数据的语句解释选择与子查询一起使用;有关更多信息,请参见第13.2.10.8节,“派生表”