10.9 预览功能:支持 SHOW ANALYZE 和 EXPLAIN FOR CONNECTION

SHOW ANALYZE

如果您曾在 MariaDB 中进行查询性能故障排除,您应该熟悉 MariaDB 的语句 ANALYZE 功能。它与某些其他数据库系统中的 EXPLAIN ANALYZE 功能类似:ANALYZE query 会运行该query并生成 EXPLAIN 输出,并补充查询执行数据

ANALYZE SELECT *
FROM orders, customer 
WHERE
  customer.c_custkey = orders.o_custkey AND
  customer.c_acctbal < 0 AND
  orders.o_totalprice > 200*1000
+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+
| id | select_type | table    | type | possible_keys | key         | key_len | ref                | rows   | r_rows | filtered | r_filtered | Extra       |
+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+
|  1 | SIMPLE      | customer | ALL  | PRIMARY,...   | NULL        | NULL    | NULL               | 149095 | 150000 |    18.08 |       9.13 | Using where |
|  1 | SIMPLE      | orders   | ref  | i_o_custkey   | i_o_custkey | 5       | customer.c_custkey |      7 |     10 |   100.00 |      30.03 | Using where |
+----+-------------+----------+------+---------------+-------------+---------+--------------------+--------+--------+----------+------------+-------------+

还有 ANALYZE FORMAT=JSON 变体,它提供更多信息:它生成 EXPLAIN FORMAT=JSON 输出,并补充观察到的运行时统计信息。统计信息字段以“r_”开头

  • “r_loops” 显示每个查询计划元素执行了多少次
  • “r_rows” 显示平均产生了多少行
  • “r_total_time_ms” 显示每个查询计划元素花费了多少时间

我们在 MariaDB 一直使用 ANALYZE FORMAT=JSON 来诊断查询优化器问题,并且它已被证明非常有用。但在某些时候,我们遇到了一个有趣的障碍。我们分析的查询变得越来越大,最终查询性能问题是关于那些永远无法完成的长达一页的查询。

由于查询永远无法完成,因此您无法获取该查询的 ANALYZE [FORMAT=JSON] 输出。

MariaDB 具有 SHOW EXPLAIN 命令。它显示当前正在运行的查询的 EXPLAIN 输出。因此,我们决定将这些命令结合起来,并引入了 SHOW ANALYZE 命令。新命令的语法是

SHOW ANALYZE [FORMAT=JSON] FOR <connection_id>;

对于 FORMAT=JSON 变体,输出类似于 ANALYZE [FORMAT=JSON] 输出。r_ 成员显示截至目前已发生的执行统计信息。还有一个额外的成员 r_query_time_in_progress_ms,它显示查询已运行了多长时间

MariaDB [test]> show analyze format=json for 4\G
*************************** 1. row ***************************
SHOW ANALYZE: {
  "r_query_time_in_progress_ms": 1716,
  "query_block": {
    "select_id": 1,
    "r_loops": 1,
    "nested_loop": [
      {
        "table": {
          "table_name": "customer",
          "access_type": "ALL",
          "r_loops": 1,
          "rows": 1500,
          "r_rows": 273,
          ....

其他 r_* 成员的存在取决于执行器是否正在收集目标查询的计时信息。

如果目标查询是 ANALYZE 查询,执行器将为其收集计时信息(这会产生一些额外的 CPU 开销)。然后,SHOW ANALYZE FORMAT=JSON 将显示 r_*time_ms 成员。

如果目标查询是常规查询(如 SELECT、UPDATE、DELETE 等),则执行器将不会收集计时信息,并且 SHOW ANALYZE FORMAT=JSON 将仅显示基于计数的统计信息,例如 r_loops、r_rows 和 r_filtered。

此功能的 JIRA 任务是 MDEV-27021,预览版可在此处获取

EXPLAIN FOR CONNECTION

MariaDB 和 MySQL 都具备检查正在运行的查询的查询计划的能力。MariaDB 最早引入了此功能,并使用以下语法

EXPLAIN [FORMAT=JSON|...] FOR CONNECTION <connection_id>;

请注意,MySQL 允许生成 JSON 输出,其中包含更多详细信息。社区多次要求在 MariaDB 中添加对 MySQL 语法的支持。我们已实现了这一点,并添加了对生成 FORMAT=JSON 输出的支持。现在,在 10.9 预览版中,可以使用以下任一形式的语法

SHOW EXPLAIN [FORMAT=JSON] FOR <connection_id>;
EXPLAIN [FORMAT=JSON] FOR CONNECTION <connection_id>;

此功能的 JIRA 任务是 MDEV-10000在此处下载预览版