MySQL explain format的差异

前言

笔者在做项目时,发现新版的MySQL(现在最新版)出现explain时tree的结果,本身这个结果也看得懂,但是已经习惯表格模式,还是有点别扭,就看了官方文档,发现explain增加了tree模式和json模式,简单体验一下这2种模式和传统模式的区别。

MySQL验证

使用上次的容器MySQL

版本已经更新到9.5.0,根据官方文档:explain-analyze

SELECT @@explain_format;

发现MySQL新版本已经默认使用tree模式

设置为JSON或者TRADITIONAL也行,这个设置是非全局的。

使用demo看看其中有什么差异

JSON模式

上面设置了JSON模式,那么看看JSON是怎么样的,以JPA那篇文章的saveall为例

如果索引设置不合理,那么执行计划如下

复制代码
explain select * from demo.user where id= "0e604c36-e91e-4ebd-8ec5-2939e4ab1d55";
bash 复制代码
{
  "query": "/* select#1 */ select `demo`.`user`.`id` AS `id`,`demo`.`user`.`name` AS `name`,`demo`.`user`.`age` AS `age`,`demo`.`user`.`addr` AS `addr`,`demo`.`user`.`iid` AS `iid` from `demo`.`user` where (`demo`.`user`.`id` = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55')",
  "query_plan": {
    "inputs": [
      {
        "operation": "Table scan on user",
        "table_name": "user",
        "access_type": "table",
        "schema_name": "demo",
        "used_columns": [
          "id",
          "name",
          "age",
          "addr",
          "iid"
        ],
        "estimated_rows": 18078.0,
        "estimated_total_cost": 1960.0181818181818
      }
    ],
    "condition": "(demo.`user`.id = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55')",
    "operation": "Filter: (demo.`user`.id = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55')",
    "access_type": "filter",
    "estimated_rows": 1807.8000269383192,
    "filter_columns": [
      "demo.`user`.id"
    ],
    "estimated_total_cost": 1960.0181818181818
  },
  "query_type": "select",
  "json_schema_version": "2.0"
}

说实在的,除了数据有点啰嗦,其实跟表格方式差距不大,修改索引,看看命中索引的情况

bash 复制代码
{
  "query": "/* select#1 */ select `demo`.`user`.`id` AS `id`,`demo`.`user`.`name` AS `name`,`demo`.`user`.`age` AS `age`,`demo`.`user`.`addr` AS `addr`,`demo`.`user`.`iid` AS `iid` from `demo`.`user` where (`demo`.`user`.`id` = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55')",
  "query_plan": {
    "covering": false,
    "operation": "Index lookup on user using user_pk (id = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55')",
    "index_name": "user_pk",
    "table_name": "user",
    "access_type": "index",
    "key_columns": [
      "id"
    ],
    "schema_name": "demo",
    "used_columns": [
      "id",
      "name",
      "age",
      "addr",
      "iid"
    ],
    "estimated_rows": 1.0,
    "lookup_condition": "id = '0e604c36-e91e-4ebd-8ec5-2939e4ab1d55'",
    "index_access_type": "index_lookup",
    "lookup_references": [
      "const"
    ],
    "estimated_total_cost": 0.35
  },
  "query_type": "select",
  "json_schema_version": "2.0"
}

明显可以看到命中索引信息,尤其是评估Total cost,从1960到0.35大幅度下降,且根据B+树的结构,复杂度从全表扫描的O(n)变为O(logmN)--具体复杂度跟索引命中情况和回表有关系。

Tree模式

在MySQL 9.5.0中,Tree模式为默认模式,其实笔者也很喜欢,因为简洁就是王道。

命中索引的情况下,就说使用了那个索引的那个字段值命中,评估cost值

如果没命中索引,给出cost值

关键信息都有了,其他的一概不展示,因为对于绝大部分开发人员优化,就是索引命中和耗时优化。Tree模式作为默认模式确实很友好。

传统模式

这种模式实际上在MySQL8.0之初和之前,都是用的这种模式,其实也方便,但是不能一目了然,表格的数据比较完整,不过不少很友好,不够人性化。

命中索引

没有评估cost,其他该有的都有,不够归类总结。

ANALYZE增强模式

其实这种模式严格上讲是对原有模式的增强

EXPLAIN ANALYZE runs a statement and produces EXPLAIN output along with timing and additional, iterator-based, information about how the optimizer's expectations matched the actual execution. For each iterator, the following information is provided:

  • Estimated execution cost

    (Some iterators are not accounted for by the cost model, and so are not included in the estimate.)

  • Estimated number of returned rows

  • Time to return first row

  • Time spent executing this iterator (including child iterators, but not parent iterators), in milliseconds.

    (When there are multiple loops, this figure shows the average time per loop.)

  • Number of rows returned by the iterator

  • Number of loops

简单翻译一下:

EXPLAIN ANALYZE 运行执行计划,并生成 EXPLAIN 输出,同时提供时间信息以及额外的、基于迭代器的信息,用于说明优化器的预期与实际执行的匹配情况。对于每个迭代器,提供以下信息:

估计执行成本

(某些迭代器未被成本模型计算,因此不会包含在估算中。)

估计返回的行数

返回第一行所需时间

执行此迭代器所花费的时间(包括子迭代器,但不包括父迭代器),以毫秒为单位。

(当存在多个循环时,此数字表示每次循环的平均时间。)

迭代器返回的行数

循环次数

Tree OR JSON SUPPORT

可以使用Tree和JSON输出,建议使用tree模式,简单明了。

  • If the value of this variable is TRADITIONAL or TREE (or the synonym DEFAULT), EXPLAIN ANALYZE uses the TREE format unless the statement includes FORMAT=JSON.

  • If the value of explain_format is JSON, EXPLAIN ANALYZE uses the JSON format unless FORMAT=TREE is specified as part of the statement.

Using FORMAT=TRADITIONAL or FORMAT=DEFAULT with EXPLAIN ANALYZE always raises an error, regardless of the value of explain_format.

总结

其实MySQL的高版本的explain还是没太多的变化,默认增加了cost评估计算,这个非常直观有用,可以看出即使2~3w的数据,命中索引cost为0.35,而未命中索引为1800~2000之间的评估值,这个可以充分的说明差异,当然对于2W多的数据,即使全表扫描也不会很慢,但是随着数据的积累,这个差距会越来越大,笔者在jpa的saveall中发现,如果数据上升200多w,那么这个jpa的saveall耗时20多分钟,这个明显是缺陷,空耗数据库CPU,性能查。

其实展示方式,传统模式,Tree模式还是JSON模式,区别不大,关键是Tree和JSON模式有cost展示,笔者自己比较喜欢Tree模式,简洁,一目了然,效率高。

相关推荐
哈哈不让取名字2 小时前
用Pygame开发你的第一个小游戏
jvm·数据库·python
程序员敲代码吗2 小时前
Python异步编程入门:Asyncio库的使用
jvm·数据库·python
liux35282 小时前
MySQL主从复制技术全面解析:从基础原理到高级架构实践(八)
mysql
a程序小傲3 小时前
听说前端又死了?
开发语言·前端·mysql·算法·postgresql·深度优先
志凌海纳SmartX3 小时前
榫卯企业云平台:让企业自建云更简单
数据库
老邓计算机毕设3 小时前
SSM学生信息管理系统ow05a(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学生信息管理系统·ssm 框架·高校教育管理
小Mie不吃饭3 小时前
MySQL慢查询日志全解析:从配置到优化实践
mysql
Access开发易登软件4 小时前
数据处理中的两大基石:何时选择Excel,何时考虑Access
数据库·信息可视化·excel·vba·access