今天就跟大家聊聊有关怎么在MySQL数据库中执行计划,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
1. EXPLAIN 输出列
说下几个关键的列:
type :连接类型
possible_keys :可选的索引
key :实际执行时使用的索引
ref :ref列显示将哪些列或常量与前面key列中显示的命名的索引进行比较以从表中选择行
rows :rows列表示MySQL认为执行查询必须检查的行数
连接类型,顺序从最好到最差,依次是:
表只有一行。这是const join类型的特例。
表最多有一个匹配行,在查询开始时读取。因为只有一行,所以这一行中的列的值可以被优化器的其余部分视为常量。const表非常快,因为它们只被读取一次。
当你用PRIMARY KEY或UNIQUE索引的所有部分与常量值进行比较时,将使用const。
例如,下面的表tbl_name可以被当做const表:
SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
对于前表中的每一行组合,从这个表中读取一行。除了system和const类型,这是可能的最好的联接类型。当一个索引的所有部分都被联接使用并且索引是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;
对于前表中的行的每种组合,将从该表中读取具有匹配索引值的所有行。如果联接仅使用key的最左前缀,或者如果key不是PRIMARY KEY或UNIQUE索引(换句话说,如果联接无法基于key值选择单个行),则使用ref。如果使用的key仅匹配几行,则这是一种很好的联接类型。
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;
使用FULLTEXT索引执行连接
这种连接类型类似于ref,但是MySQL会额外搜索包含NULL值的行。此联接类型优化最常用于解析子查询。
例如,下面的例子中,MYSQL可以使用ref_or_null来处理ref_table:
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
这种连接类型表明使用了索引合并优化。在这种情况下,输出行中的key列包含使用的索引列表,而key_len包含所使用索引的最长key部分列表。
此类型将eq_ref替换为以下形式的某些IN子查询:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
与unique_subquery类似,它代替了IN子查询,但适用于以下形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
只检索给定范围内的行,并使用索引来选择行。输出行中的key列指示使用了哪个索引。key_len包含所使用的最长的key部分。对于这种类型,ref列为NULL。
使用=,<>,>,> =,<,<=,IS NULL,<=>,BETWEEN,LIKE或IN()运算符将key列与常量进行比较时,可以使用range:
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);
index连接类型与all是一样的,区别在于index连接类型扫描的时候索引树。通常,只发生在以下两种情况:
如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则仅扫描索引树。在这种情况下,“Extra”列显示“Using index”。仅索引扫描通常比ALL快,因为索引的大小通常小于表数据。
使用从索引读取数据以按索引顺序查找数据行来执行全表扫描。“Uses index”不会出现在Extra列中。
对前表的行的每个组合进行全表扫描。如果该表是未标记为const的第一个表,则通常不好,并且在所有其他情况下通常非常糟糕。通常,可以通过添加索引来避免ALL,这些索引允许基于早期表中的常量值或列值从表中检索行。
关于Extra列的输出,只说几个常见的:
MySQL必须做一次额外操作,以找出如何按排序顺序检索行。排序是通过根据联接类型遍历所有行并存储与WHERE子句匹配的所有行的排序key和指向该行的指针来完成的。然后对key进行排序,并按排序顺序检索行。
仅使用索引树中的信息从表中检索列信息,而不需要执行额外的查找来读取实际行。当查询只使用属于单个索引的列时,可以使用此策略。
为了解析查询,MySQL需要创建一个临时表来保存结果。通常,如果查询包含以不同方式展示列的GROUP BY和ORDER BY子句,则会发生这种情况。
WHERE子句用于限制哪些行匹配下一个表或发送给客户端。除非你打算从表中获取或检查所有行,否则如果额外的值没有使用where,并且表连接类型是all或index,则查询中可能出现错误。
在某些情况下,MySQL可能会使用一个索引来满足ORDER BY子句,从而避免执行filesort操作所涉及的额外排序。
假设在(key_part1, key_part2)上有一个索引,下面的查询可以使用索引来解析ORDER BY部分。优化器是否真的这样做,取决于如果还必须读取索引之外的时,读取索引是否比表扫描更有效。
SELECT * FROM t1 ORDER BY key_part1, key_part2;
上面的语句,查询使用SELECT *,这可能会选择比key_part1和key_part2更多的列。在这种情况下,扫描整个索引并查找表行以查找索引中未包含的列可能比扫描表并排序结果要昂贵。如果是这样,则优化器不太可能使用索引。如果SELECT *仅选择索引列,则使用索引并避免排序。
下面这个查询中,key_part1是常量,因此通过索引访问的所有行都按key_part2顺序排列,并且如果WHERE子句的选择性足以使索引范围扫描比表扫描便宜,则在(key_part1,key_part2)上的索引可以避免排序:
SELECT * FROM t1 WHERE key_part1 = constant ORDER BY key_part2;
看完上述内容,你们对怎么在MySQL数据库中执行计划有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。