新特性解读 | 针对用户定制不同格式执行计划

2023-02-13 13:26:37 浏览数 (1)

作者:杨涛涛

资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。

本文来源:原创投稿

*可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


记得以前在项目现场时,客户曾提出一个这样的需求:在 MySQL 数据库里查看语句的执行计划,能否针对不同的用户使用同样的语句定制输出不同的格式?比如用户张三不想执行 explain format='tree' ,只想简单执行 explain就可以输出tree 格式的执行计划;同样用户李四也不想执行 explain format='json' ,只想简单执行 explain就可以输出 json 格式的执行计划。

好吧!当时MySQL 没有提供这样的功能,而且我也觉得这样的功能非必需,于是我给了三个可选方法:
第一: 自己写个脚本对 MySQL 客户端进行封装;
第二:建议直接用 SHELL 来调用 MySQL 客户端,并且定制类似 SHELL 的别名;
第三:别偷懒...。
最后经过一系列探讨,客户选择了选项三!

不过幸运的是,最新版本 MySQL 8.0.32 最近发布,提供了这样的功能。用一个变量来针对不同的用户可以定制输出不同格式的执行计划,变量名为:explain_format 。通过设置不同的值,来使得 explain 语句 输出不同格式的执行计划。

我们来体验下这个功能:
设置默认格式为 tree 。
代码语言:sql复制
mysql:8.0.32-cluster:ytt>set @@explain_format=tree;
Query OK, 0 rows affected (0.00 sec)

<mysql:8.0.32-cluster:ytt>explain table t1G
*************************** 1. row ***************************
EXPLAIN: -> Table scan on t1  (cost=1.20 rows=2)

1 row in set (0.00 sec)
设置默认格式为 traditional ,也就是传统模式。
代码语言:sql复制
mysql:8.0.32-cluster:ytt>set @@explain_format=traditional;
Query OK, 0 rows affected (0.00 sec)

<mysql:8.0.32-cluster:ytt>explain table t1G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)
有了这个功能,就仿佛奥特曼看到了光。 那接下来,我们来实现本篇开头的需求:语句相同,用户不同,执行计划的输出格式不同。

新建两个用户,一个是 zhangsan ,另外一个是 lisi 。zhangsan 的执行计划格式为:explain format='tree' ; lisi 的执行计划格式为:explain format='json' 。

分别创建这两个用户:

代码语言:sql复制
mysql:8.0.32-cluster:ytt>create user zhangsan;
Query OK, 0 rows affected (0.00 sec)

<mysql:8.0.32-cluster:ytt>create user lisi;
Query OK, 0 rows affected (0.01 sec)

<mysql:8.0.32-cluster:ytt>grant select on ytt.* to zhangsan;
Query OK, 0 rows affected (0.01 sec)

<mysql:8.0.32-cluster:ytt>grant select on ytt.* to lisi;
Query OK, 0 rows affected (0.01 sec)

用户 zhangsan 连接 MySQL 后,自动设置执行计划格式:

代码语言:sql复制
root@ytt-super:/home/ytt# mysql -uzhangsan --init-command='set @@explain_format=tree' -D ytt
...
<mysql:8.0.32-cluster:ytt>explain table t1G
*************************** 1. row ***************************
EXPLAIN: -> Table scan on t1  (cost=1.20 rows=2)

1 row in set (0.00 sec)

同样的方法,用户 lisi 则这样连接 MySQL :结果太长,我就不贴了。

代码语言:shell复制
root@ytt-super:/home/ytt# mysql -ulisi --init-command='set @@explain_format=json' -D ytt

0 人点赞