您现在的位置是:首页 > 文章详情

MySQL 8.1 和 8.2 中 EXPLAIN 的新玩法

日期:2024-01-02点击:63

从 MySQL 8.1 开始 EXPLAIN 引入了 INTO 子句,它允许将 EXPLAIN 查询的输出存储在用户变量中,而不是将其返回给客户端。目前仅支持 JSON 格式,但这对于大多数用例来说应该足够了。

作者:Magnus Brevik

原文地址:https://dev.mysql.com/blog-archive/explain-into-and-explain-for-schema-in-mysql-81-and-82/

EXPLAIN INTO

从 MySQL 8.1 开始 EXPLAIN 引入了 INTO 子句,它允许将 EXPLAIN 查询的输出存储在用户变量中,而不是将其返回给客户端。目前仅支持 JSON 格式,但这对于大多数用例来说应该足够了。

EXPLAIN 的输出存储在用户变量之后,就可以将它当成 JSON 对象操作。这使您能够以编程方式直接从 EXPLAIN中提取、操作和存储数据到数据库中。

举个例子:

mysql> SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id; +-------------+----------+ | name | quantity | +-------------+----------+ | Screwdriver | 23 | | Screwdriver | 1 | | Locket | 17 | | Armoire | 42 | | Armoire | 16 | +-------------+----------+ 

如果只对此次查询的开销成本感兴趣,可以先将查询定义为为 @explain_output

mysql> EXPLAIN FORMAT=JSON INTO @explain_output SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id; Query OK, 0 rows affected (0,00 sec) 

现在,从这个 EXPLAIN 中得到的唯一输出是“Query OK”。如果我们想查看完整的 EXPLAIN 输出,我们可以选择 @explain_output,但是完整的 JSON 输出会占用很大的空间,而且我只对开销(cost )感兴趣。为了从 JSON 对象中提取,只需使用 MySQL 的 JSON 函数对指定的 JSON 对象处理即可。

mysql> SELECT JSON_EXTRACT(@explain_output, "$.query_block.cost_info.query_cost") AS query_cost; +------------+ | query_cost | +------------+ | "1.60" | +------------+ 

EXPLAIN SCHEMA

从 MySQL 8.2 开始 EXPLAIN 引入了 FOR SCHEMA 子句。它允许在当前 SCHEMA 之外的其他 SCHEMA 中执行 EXPLAIN 查询。这使得创建一个存储过程 PROCEDURE 来解释每个 SCHEMA 中最常运行的查询并收集有关它们的统计信息成为可能。

如果当前的 SCHEMA 与我们要查询的表所在的 SCHEMA 不同,我们可以

mysql> USE statistics; mysql> EXPLAIN FORMAT=TREE FOR SCHEMA customer1 SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id; -> Nested loop inner join (cost=2.3 rows=5) -> Table scan on items (cost=0.55 rows=3) -> Index lookup on orders using fk_item_id (item_id=items.id) (cost=0.472 rows=1.67) 

这对于大多数 EXPLAIN 使用的情况可能不太有用,但是如果我们有多个具有相同表结构的 SCHEMA,并且想要一次性收集所有 SCHEMA 的统计信息,我们可以创建一个存储过程 PROCEDURE 来为我们做到这一点:

DELIMITER | CREATE PROCEDURE explain_query_for_schema(IN schema_name VARCHAR(64), IN query VARCHAR(1000)) BEGIN SET @explain_stmt = CONCAT("EXPLAIN FORMAT=JSON INTO @explain_output FOR SCHEMA ", schema_name, " ", query); PREPARE stmt FROM @explain_stmt; EXECUTE stmt; INSERT INTO explain_outputs (schema_name, query, explain_output) VALUES (schema_name, query, @explain_output); END | CREATE PROCEDURE explain_query_for_all_schemas(IN query VARCHAR(1000)) BEGIN DECLARE done BOOLEAN DEFAULT FALSE; DECLARE schema_name VARCHAR(64); DECLARE cur_schema_names CURSOR FOR SELECT schema_name_table.schema_name FROM schema_name_table; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur_schema_names; explain_loop: LOOP FETCH cur_schema_names INTO schema_name; IF done THEN LEAVE explain_loop; END IF; CALL explain_query_for_schema(schema_name, query); END LOOP; CLOSE cur_schema_names; END | DELIMITER ; SET @query = "SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id"; CALL explain_query_for_all_schemas(@query); SELECT schema_name, query, JSON_EXTRACT(explain_output, "$.query_block.cost_info.query_cost") AS query_cost, created_at FROM explain_outputs; +-------------+---------------------------------------------------------------------------+------------+---------------------+ | schema_name | query | query_cost | created_at | +-------------+---------------------------------------------------------------------------+------------+---------------------+ | customer1 | SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id | "2.30" | 2023-11-14 20:56:47 | | customer2 | SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id | "0.70" | 2023-11-14 20:56:47 | | customer3 | SELECT name, quantity FROM orders JOIN items ON orders.item_id = items.id | "9.10" | 2023-11-14 20:56:47 | +-------------+---------------------------------------------------------------------------+------------+---------------------+ 

就是这样。EXPLAIN 的两个相对简单的扩展乍一看可能并不重要,但使存储过程能够以编程方式处理 EXPLAIN 输出。我们自己将其用于 《使用 MySQL Autopilot Indexing 删除索引猜测值》 这个案例中,其中 EXPLAIN INTOEXPLAIN FOR SCHEMA 对于收集数据以建议更好的索引至关重要。我们希望它对您和我们一样有用。

如果您想了解更多信息,这些都记录在 MySQL EXPLAIN 文档 中。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。

SQLE 获取

类型 地址
版本库 https://github.com/actiontech/sqle
文档 https://actiontech.github.io/sqle-docs/
发布信息 https://github.com/actiontech/sqle/releases
数据审核插件开发文档 https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse
原文链接:https://my.oschina.net/actiontechoss/blog/10560322
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章