面试官:不会望 Explain实走计划,简历敢写 SQL 优化?

时间:2020-06-23 03:01 点击:202

原标题:面试官:不会望 Explain实走计划,简历敢写 SQL 优化?

来自公多号: 程序员内点事

来自公多号: 程序员内点事

昨天正午在食堂,和部分的技术大牛们坐在一桌吃饭,行为一个微贱技术渣仔稳定的吃着饭,听大佬们高谈阔论,钻研各栽高端技术,吾TM也想发言可实在插不上嘴。

聊着聊着骤然说到他上午面试了一个做事6年的程序员,外情挺复杂,他说:吾望他简历写着熟识SQL语句调优,就问了下 Explain实走计划怎么望?效果这老哥一问三不知,做事6年这么基础的东西都不晓畅!

感受到了大佬的王之轻蔑,回到工位吾就最先稳定写这个,哎~ 吾TM也不太懂 Explain,老哥你这是针对吾啊!哭唧唧~

Explain有什么用

当Explain与 SQL语句一首行使时,MySQL会表现来自优化器关于SQL实走的新闻。也就是说,MySQL注释了它将如那里理该语句,包括如何连接外以及什么挨次连接外等。

外的添载挨次

sql的查询类型

能够用到哪些索引,哪些索引又被实际行使

外与外之间的引用有关

一个外中有多少走被优化器查询.....

外的添载挨次

sql的查询类型

能够用到哪些索引,哪些索引又被实际行使

打开全文

外与外之间的引用有关

一个外中有多少走被优化器查询.....

Explain实走计划包含字段新闻如下:别离是 id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra12个字段。

下边吾们会结相符详细的SQL示例,详细的解读每个字段以及每个字段平分歧参数的含义,以下一切示例数据库版本为 MySQL.5.7.17。

mysql> selectversionfromdual;

------------

| version |

------------

| 5.7.17-log |

------------

吾们创建三张外 one、two、three,外之间的有关 one.two_id = two.two_id AND two.three_id = three.three_id。

Explain实走计划详解一、id

id::外示查询中实走select子句或者操作外的挨次, id 的值越大,代外优先级越高,越先实走 。 id大致会展现 3栽情况:

1、id相通

望到三条记录的id都相通,能够理解成这三个外为一组,具有同样的优先级,实走挨次由上而下,详细挨次由优化器决定。

mysql> EXPLAINSELECT* FROMone o,two t, three r WHEREo.two_id = t.two_id ANDt.three_id = r.three_id;

---- ------------- ------- ------------ -------- --------------- --------- --------- ---------------------- ------ ---------- ----------------------------------------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ -------- --------------- --------- --------- ---------------------- ------ ---------- ----------------------------------------------------

| 1 | SIMPLE | o | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100 | NULL |

| 1 | SIMPLE | t | NULL | ALL | PRIMARY | NULL | NULL | NULL | 2 | 50 | Using where; Using join buffer (Block Nested Loop) |

| 1 | SIMPLE | r | NULL | eq_ref | PRIMARY | PRIMARY | 4 | xin-slave.t.three_id | 1 | 100 | NULL |

---- ------------- ------- ------------ -------- --------------- --------- --------- ---------------------- ------ ---------- ----------------------------------------------------

2、id分歧

倘若吾们的 SQL中存在子查询,那么 id的序号会递添,id值越大优先级越高,越先被实走 。当三个外挨次嵌套,发现最里层的子查询 id最大,最先实走。

mysql> EXPLAINselect* fromone o whereo.two_id = ( selectt.two_id fromtwo t wheret.three_id = ( selectr.three_id fromthree r wherer.three_name= '吾是第三外2'));

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| 1 | PRIMARY | o | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

| 2 | SUBQUERY | t | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

| 3 | SUBQUERY | r | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

3、以上两栽同时存在

将上边的 SQL稍微修改一下,增补一个子查询,发现 id的以上两栽同时存在。相通id划分为一组,云云就有三个组,同组的从上去下挨次实走,分歧组 id值越大,优先级越高,越先实走。

mysql> EXPLAINselect* fromone o whereo.two_id = ( selectt.two_id fromtwo t wheret.three_id = ( selectr.three_id fromthree r wherer.three_name= '吾是第三外2')) ANDo.one_id in( selectone_id fromone whereo.one_name= "吾是第一外2");

---- ------------- ------- ------------ -------- --------------- --------- --------- -------------------- ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ -------- --------------- --------- --------- -------------------- ------ ---------- -------------

| 1 | PRIMARY | o | NULL | ALL | PRIMARY | NULL | NULL | NULL | 2 | 50 | Using where |

| 1 | PRIMARY | one | NULL | eq_ref | PRIMARY | PRIMARY | 4 | xin-slave.o.one_id | 1 | 100 | Using index |

| 2 | SUBQUERY | t | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

| 3 | SUBQUERY | r | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

---- ------------- ------- ------------ -------- --------------- --------- --------- -------------------- ------ ---------- -------------

二、select_type

select_type:外示 select查询的类型,主要是用于区分各栽复杂的查询,例如:清淡查询、说相符查询、子查询等。

1、SIMPLE

SIMPLE:外示最浅易的 select 查询语句,也就是在查询中不包含子查询或者 union交并差集等操作。

2、PRIMARY

PRIMARY:当查询语句中包含任何复杂的子片面,最外层查询则被标记为PRIMARY。

3、SUBQUERY

SUBQUERY:当 select或 where列外中包含了子查询,该子查询被标记为:SUBQUERY。

4、DERIVED

DERIVED:外示包含在from子句中的子查询的select,在吾们的 from列外中包含的子查询会被标记为derived。

5、UNION

UNION:倘若union后边又展现的select语句,则会被标记为union;若 union包含在 from子句的子查询中,外层 select将被标记为 derived。

6、UNION RESULT

UNION RESULT:代外从union的一时外中读取数据,而table列的<union1,4>外示用第一个和第四个select的效果进走union操作。

mysql> EXPLAINselectt.two_name, ( selectone.one_id fromone) o from( selecttwo_id,two_name fromtwo wheretwo_name = '') t union( selectr.three_name,r.three_id fromthree r);

------ -------------- ------------ ------------ ------- --------------- --------- --------- ------ ------ ---------- -----------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

------ -------------- ------------ ------------ ------- --------------- --------- --------- ------ ------ ---------- -----------------

| 1 | PRIMARY | two | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50 | Using where |

| 2 | SUBQUERY | one | NULL | index | NULL | PRIMARY | 4 | NULL | 2 | 100 | Using index |

| 4 | UNION | r | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100 | NULL |

| NULL | UNION RESULT | <union1,4> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |

------ -------------- ------------ ------------ ------- --------------- --------- --------- ------ ------ ---------- -----------------

三、table

查询的外名,并纷歧定是实在存在的外,有又名表现又名,也能够为一时外,例如上边的DERIVED、 <union1,4>等。

四、partitions

查询时匹配到的分区新闻,对于非分区外值为NULL,当查询的是分区外时,partitions表现分区外命中的分区情况。

---- ------------- ---------------- --------------------------------- ------- --------------- --------- --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ---------------- --------------------------------- ------- --------------- --------- --------- ------ ------ ---------- -------------

| 1 | SIMPLE | one | p201801,p201802,p201803,p300012 | index | NULL | PRIMARY | 9 | NULL | 3 | 100 | Using index |

---- ------------- ---------------- --------------------------------- ------- --------------- --------- --------- ------ ------ ---------- -------------

五、type

type:查询行使了何栽类型,它在 SQL优化中是一个专门主要的指标,以下性能从益到坏挨次是:system> const> eq_ref> ref> ref_or_null> index_merge> unique_subquery> index_subquery> range> index> ALL

1、system

system:当外仅有一走记录时(体系外),数据量很少,往往不必要进走磁盘IO,速度专门快。

2、const

const:外示查询时命中 primary key主键或者 unique唯一索引,或者被连接的片面是一个常量(const)值。这类扫描效果极高,返回数据量少,速度专门快。

mysql> EXPLAINSELECT* fromthree wherethree_id= 1;

---- ------------- ------- ------------ ------- --------------- --------- --------- ------- ------ ---------- -------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------- ------ ---------- -------

| 1 | SIMPLE | three | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100 | NULL |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------- ------ ---------- -------

3、eq_ref

eq_ref:查询时命中主键primary key或者 unique key索引, type就是 eq_ref。

mysql> EXPLAINselecto.one_name fromone o ,two t whereo.one_id = t.two_id ;

---- ------------- ------- ------------ -------- --------------- ---------- --------- -------------------- ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ -------- --------------- ---------- --------- -------------------- ------ ---------- -------------

| 1 | SIMPLE | o | NULL | index | PRIMARY | idx_name | 768 | NULL | 2 | 100 | Using index |

| 1 | SIMPLE | t | NULL | eq_ref | PRIMARY | PRIMARY | 4 | xin-slave.o.one_id | 1 | 100 | Using index |

---- ------------- ------- ------------ -------- --------------- ---------- --------- -------------------- ------ ---------- -------------

4、ref

ref:区别于eq_ref,ref外示行使非唯一性索引,会找到许多个相符条件的走。

mysql> selecto.one_id fromone o whereo.one_name = "xin";

--------

| one_id |

--------

| 1 |

| 3 |

-------- ```

```sql

mysql> EXPLAINselecto.one_id fromone o whereo.one_name = "xin";

---- ------------- ------- ------------ ------ --------------- ---------- --------- ------- ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ---------- --------- ------- ------ ---------- -------------

| 1 | SIMPLE | o | NULL | ref | idx_name | idx_name | 768 | const | 1 | 100 | Using index |

---- ------------- ------- ------------ ------ --------------- ---------- --------- ------- ------ ---------- -------------

5、ref_or_null

ref_or_null:这栽连接类型相通于 ref,区别在于 MySQL会额外搜索包含NULL值的走。

mysql> EXPLAINselecto.one_id fromone o whereo.one_name = "xin"ORo.one_name ISNULL;

---- ------------- ------- ------------ ------------- --------------- ---------- --------- ------- ------ ---------- --------------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------------- --------------- ---------- --------- ------- ------ ---------- --------------------------

| 1 | SIMPLE | o | NULL | ref_or_null | idx_name | idx_name | 768 | const | 3 | 100 | Using where; Using index |

---- ------------- ------- ------------ ------------- --------------- ---------- --------- ------- ------ ---------- --------------------------

6、index_merge

index_merge:行使了索引相符并优化手段,查询行使了两个以上的索引。

下边示例中同时行使到主键one_id和 字段one_name的idx_name索引 。

mysql> EXPLAINselect* fromone o whereo.one_id > 1ando.one_name = 'xin';

---- ------------- ------- ------------ ------------- ------------------ ------------------ --------- ------ ------ ---------- ------------------------------------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------------- ------------------ ------------------ --------- ------ ------ ---------- ------------------------------------------------

| 1 | SIMPLE | o | NULL | index_merge | PRIMARY,idx_name | idx_name,PRIMARY | 772,4 | NULL | 1 | 100 | Using intersect(idx_name,PRIMARY); Using where |

---- ------------- ------- ------------ ------------- ------------------ ------------------ --------- ------ ------ ---------- ------------------------------------------------

7、unique_subquery

unique_subquery:替换下面的 IN子查询,子查询返回不重复的荟萃。

value IN ( SELECTprimary_key FROMsingle_table WHEREsome_expr)

8、index_subquery

index_subquery:区别于unique_subquery,用于非唯一索引,新闻中心能够返回重复值。

value IN ( SELECTkey_column FROMsingle_table WHEREsome_expr)

9、range

range:行使索引选择走,仅检索给定周围内的走。浅易点说就是针对一个有索引的字段,给定周围检索数据。在where语句中行使 bettween...and、<、>、<=、in等条件查询 type都是 range。

举个栗子:three外中three_id为唯一主键,user_id清淡字段未建索引。

mysql> EXPLAINSELECT* fromthree wherethree_id BETWEEN2AND3;

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| 1 | SIMPLE | three | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 1 | 100 | Using where |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

从效果中望到只有对竖立了索引的字段,做周围检索 type才是 range。

mysql> EXPLAINSELECT* fromthree whereuser_id BETWEEN2AND3;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| 1 | SIMPLE | three | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

10、index

index:Index与ALL其实都是读全外,区别在于index是遍历索引树读取,而ALL是从硬盘中读取。

下边示例:three_id为主键,不带 where条件全外查询 ,type效果为index。

mysql> EXPLAINSELECTthree_id fromthree ;

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| 1 | SIMPLE | three | NULL | index | NULL | PRIMARY | 4 | NULL | 1 | 100 | Using index |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

11、ALL

ALL:将遍历全外以找到匹配的走,性能最差。

mysql> EXPLAINSELECT* fromtwo ;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| 1 | SIMPLE | two | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100 | NULL |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

六、possible_keys

possible_keys:外示在MySQL中议定哪些索引,能让吾们在外中找到想要的记录,一旦查询涉及到的某个字段上存在索引,则索引将被列出, 但这个索引并不定一会是最后查询数据时所被用到的索引。详细请参考上边的例子。

七、key

key:区别于possible_keys,key是查询中实际行使到的索引,若异国行使索引,表现为NULL。详细请参考上边的例子。

当 type为 index_merge时,能够会表现多个索引。

当 type为 index_merge时,能够会表现多个索引。

key_len:外示查询用到的索引长度(字节数),原则上长度越短越益 。

单列索引,那么必要将整个索引长度算进去;

多列索引,不是一切列都能用到,必要计算查询中实际用到的列。

单列索引,那么必要将整个索引长度算进去;

多列索引,不是一切列都能用到,必要计算查询中实际用到的列。

仔细: key_len 只计算 where 条件中用到的索引长度,而排序和分组即便是用到了索引,也不会计算到 key_len 中。

仔细: key_len 只计算 where 条件中用到的索引长度,而排序和分组即便是用到了索引,也不会计算到 key_len 中。

ref:常见的有:const,func,null,字段名。

当行使常量等值查询,表现const,

当有关查询时,会表现响答有关外的有关字段

倘若查询条件行使了外达式、函数,或者条件列发生内部隐式转换,能够表现为func

其他情况null

当行使常量等值查询,表现const,

当有关查询时,会表现响答有关外的有关字段

倘若查询条件行使了外达式、函数,或者条件列发生内部隐式转换,能够表现为func

其他情况null

rows:以外的统计新闻和索引行使情况,估算要找到吾们所需的记录,必要读取的走数。

这是评估SQL性能的一个比较主要的数据,mysql必要扫描的走数,很直不都雅的表现 SQL性能的益坏,清淡情况下 rows值越幼越益。

mysql> EXPLAINSELECT* fromthree;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| 1 | SIMPLE | three | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | NULL |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

十一、filtered

filtered这个是一个百分比的值,外里相符条件的记录数的百分比。浅易点说,这个字段外示存储引擎返回的数据在经过过滤后,剩下已足条件的记录数目的比例。

在MySQL.5.7版本以前想要表现filtered必要行使explain extended命令。MySQL.5.7后,默认explain直接表现partitions和filtered的新闻。

十二、Extra

Extra:不正当在其他列中表现的新闻,Explain中的许多额外的新闻会在 Extra字段表现。

1、Using index

Using index:吾们在响答的 select操作中行使了隐瞒索引,一般一点讲就是查询的列被索引隐瞒,行使到隐瞒索引查询速度会专门快,SQl优化中理想的状态。

什么又是隐瞒索引?

一条 SQL只必要议定索引就能够返回,吾们所必要查询的数据(一个或几个字段),而不消议定二级索引,查到主键之后再议定主键查询整走数据(select *)。

one_id外为主键

mysql> EXPLAINSELECTone_id fromone ;

---- ------------- ------- ------------ ------- --------------- ------------ --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- ------------ --------- ------ ------ ---------- -------------

| 1 | SIMPLE | one | NULL | index | NULL | idx_two_id | 5 | NULL | 3 | 100 | Using index |

---- ------------- ------- ------------ ------- --------------- ------------ --------- ------ ------ ---------- -------------

仔细:想要行使到隐瞒索引,吾们在 select时只掏出必要的字段,不走select *,而且该字段建了索引。

mysql> EXPLAINSELECT* fromone ;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

| 1 | SIMPLE | one | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | NULL |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------

2、Using where

Using where:查询时未找到可用的索引,进而议定where条件过滤获取所需数据,但要仔细的是并不是一切带where语句的查询都会表现Using where。

下边示例create_time并未用到索引,type为 ALL,即MySQL议定全外扫描后再按where条件筛选数据。

mysql> EXPLAINSELECTone_name fromone wherecreate_time = '2020-05-18';

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| 1 | SIMPLE | one | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

3、Using temporary

Using temporary:外示查询后效果必要行使一时外来存储,清淡在排序或者分组查询时用到。

mysql> EXPLAINSELECTone_name fromone whereone_id in( 1, 2) groupbyone_name;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

| 1 | SIMPLE | one | NULL | range| NULL | NULL | NULL | NULL | 3 | 33.33 | Using where; Using temporary; Using filesort |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- -------------

4、Using filesort

Using filesort:外示无法行使索引完善的排序操作,也就是ORDER BY的字段异国索引,清淡云云的SQL都是必要优化的。

mysql> EXPLAINSELECTone_id fromone ORDERBYcreate_time;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

| 1 | SIMPLE | one | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

倘若ORDER BY字段有索引就会用到隐瞒索引,相比实走速度快许多。

mysql> EXPLAINSELECTone_id fromone ORDERBYone_id;

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

| 1 | SIMPLE | one | NULL | index | NULL | PRIMARY | 4 | NULL | 3 | 100 | Using index |

---- ------------- ------- ------------ ------- --------------- --------- --------- ------ ------ ---------- -------------

5、Using join buffer

Using join buffer:在吾们联外查询的时候,倘若外的连接条件异国用到索引,必要有一个连接缓冲区来存储中心效果。

先望一下有索引的情况:连接条件 one_name、two_name都用到索引。

mysql> EXPLAINSELECTone_name fromone o,two t whereo.one_name = t.two_name;

---- ------------- ------- ------------ ------- --------------- ---------- --------- ---------------------- ------ ---------- --------------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------- --------------- ---------- --------- ---------------------- ------ ---------- --------------------------

| 1 | SIMPLE | o | NULL | index | idx_name | idx_name | 768 | NULL | 3 | 100 | Using where; Using index |

| 1 | SIMPLE | t | NULL | ref | idx_name | idx_name | 768 | xin-slave.o.one_name | 1 | 100 | Using index |

---- ------------- ------- ------------ ------- --------------- ---------- --------- ---------------------- ------ ---------- --------------------------

接下来删失踪 连接条件 one_name、two_name的字段索引。发现Extra列变成 Using join buffer,type均为全外扫描,这也是SQL优化中必要仔细的地方。

mysql> EXPLAINSELECTone_name fromone o,two t whereo.one_name = t.two_name;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------------------------------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------------------------------------------

| 1 | SIMPLE | t | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100 | NULL |

| 1 | SIMPLE | o | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where; Using join buffer (Block Nested Loop) |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------------------------------------------

6、Impossible where

Impossible where:外示在吾们用不太切确的where语句,导致异国相符条件的走。

mysql> EXPLAINSELECTone_name fromone WHERE1= 2;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------

| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ------------------

7、No tables used

No tables used:吾们的查询语句中异国FROM子句,或者有 FROM DUAL子句。

mysql> EXPLAINselectnow;

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |

---- ------------- ------- ------------ ------ --------------- ------ --------- ------ ------ ---------- ----------------

Extra列的新闻专门专门多,这边就不再逐一列举了,详见 MySQL官方文档 :https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#jointype_index_merge

总结

上边只是浅易介绍了下 Explain实走计划各个列的含义,晓畅它不光仅是要搪塞面试,在实际开发中也频繁会用到。比如对慢SQL进走分析,倘若连实走计划效果都不会望,那还谈什么SQL优化呢?

●编号 517,输入编号直达本文


当前网址:http://www.hlmyyyweo.cn/45544290/2402768.html
tag:面试,官,不会,望,Explain,实走,计划,简历,敢写,

发表评论 (202人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称: 验证码:点击我更换图片
最新评论

Powered by 喀喇沁左翼蒙古族自治县华赀建筑设备公司 @2014 RSS地图 html地图

Copyright 365站群 © 2013-2018 360 版权所有