所在的位置: mysql >> mysql发展 >> MySQL8018加强EXPLAIN

MySQL8018加强EXPLAIN

北京儿童医院手足癣 http://disease.39.net/bjzkbdfyy/210629/9121641.html
在mysql8.0.18版本之前,查看一个sql语句的执行计划,基本职能看到,sql是否走索引,使用哪个索引,是否是全部扫描,是否用到文件排序等等,如下所示这样用表格方式展示,不直观,不是很方便去定位sql语句的性能瓶颈点,而且没有sql在每一步需要的cost,和预测执行时间。经过mysql社区贡献,这些痛点都一一解决,现在新版本支持以tree方式展现,而且在关键步骤都有cost,可以非常方便,直观的看到sql哪一步有性能瓶颈,下面个一个示例mysqlEXPLAINFORMAT=treeselecta.name,a.depno,b.namefromt_test1ainnerjoint_test2bona.depno=b.depno;

-Innerhashjoin(a.depno=b.depno)(cost=2.60rows=6)-Tablescanona(cost=0.15rows=6)-Hash-Indexscanonbusingname(cost=0.55rows=3)

1rowinset(0.03sec)那有没有更高级的功能呢,在每一个步骤展示预估执行时间,这个在MySQL8.0.18同样支持,在explain后面加上ANALYZE就可以mysqlEXPLAINANALYZEselecta.name,a.depno,b.namefromt_test1ainnerjoint_test2bona.depno=b.depno;

-Innerhashjoin(a.depno=b.depno)(cost=2.60rows=6)(actualtime=3...3.rows=6loops=1)-Tablescanona(cost=0.15rows=6)(actualtime=0...0.rows=6loops=1)-Hash-Indexscanonbusingname(cost=0.55rows=3)(actualtime=1...1.rows=3loops=1)

1rowinset(0.03sec)在这里观察仔细的小伙伴,会发现,actualtime有两个时间,这两个时间,我解释一下Actualtime获取第一行的消耗的时间(inmilliseconds)Actualtime获取第所有行的消耗的时间(inmilliseconds)可能有的小伙伴会问,actualtime=1...1.rows=3loops=1),为什么获取第一条记录要1.,而获取3条记录不是5.,而是1.,这是因为,这3条记录都在一个page页,数据库最小读取单位是page页,一次IO就能把3条记录读取,后面的动作都是在内存里操作,基本不消耗时间。在这里我再延伸讲解一下,数据库的二级索引,大家还是看上面的sql执行计划selecta.name,a.depno,b.namefromt_test1ainnerjoint_test2bona.depno=b.depnomysqlshowcreatetablet_test2\G;***************************1.row***************************Table:t_test2CreateTable:CREATETABLE`t_test2`(`depno`int(11)NOTNULL,`name`char(20)DEFAULTNULL,PRIMARYKEY(`depno`),KEY`name`(`name`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4__ai_ci1rowinset(0.02sec)不知道小伙伴们,发现没有,possible_keys为PRIMARY,但是key却是name,而不是depno。很奇怪吧,这里有2个原因原因一:在select要查询的列是t_test2表的name列原因二:join条件是主键列depno在这里就不得不先说一下mysql的二级索引,在mysql数据中所有的数据都是存储在索引中,主键基本都是聚簇索引,存储是记录行,二级索引,存储的是索引列值和主键值。下面用图来说明回到上面sql语句的执行计划,为什么用了name列的二级索引,这是因为二级索引里存储了name和depno两个值,sql语句只需要扫描name索引,就可以获取需要的数据,而不用再去访问主键的聚簇索引。


转载请注明:http://www.aierlanlan.com/tzrz/6025.html