基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
定位和分析慢查询
更新时间:2026-04-07 20:57:20
在数据库运行过程中,若发现系统性能下降或某些查询长期未完成,可通过以下方法快速定位并分析慢查询的执行计划。
本文提供了一套基于系统视图(GV$OB_PROCESSLIST、GV$OB_PLAN_CACHE_PLAN_STAT、GV$OB_PLAN_CACHE_PLAN_EXPLAIN)的分析流程,用来查找慢查询和对应执行计划。
示例场景
假设存在一个长时间运行的慢查询(如 SELECT SLEEP(1000) FROM T1;),我们可通过以下步骤定位并分析其执行计划:
-- 创建测试表并插入数据
CREATE TABLE T1 (C1 INT, C2 INT);
INSERT INTO T1 VALUES (1, 1);
-- 发起慢查询(执行时间 1000 秒)
SELECT SLEEP(1000) FROM T1;
分析流程
步骤 1:定位慢 SQL
通过 GV$OB_PROCESSLIST 视图筛选出当前正在执行的活跃 SQL,并按执行时间排序,快速定位最慢的查询。
-- 登录 sys 租户执行以下查询
SELECT USER, -- 用户名
tenant, -- 租户名
sql_id, -- SQL 标识
CONCAT(time, 's') AS time, -- 已执行时间
info, -- SQL 语句内容
svr_ip, -- 执行节点 IP
svr_port, -- 执行节点端口
trace_id -- 追踪 ID(用于进一步分析)
FROM GV$OB_PROCESSLIST
WHERE STATE = 'ACTIVE' -- 筛选活跃状态的查询
ORDER BY time DESC
LIMIT 1;
示例输出:
+------+----------+----------------------------------+------+-----------------------------------------------------------------------------------------------------------------+----------------+----------+------------------------------------+
| USER | tenant | sql_id | time | info | svr_ip | svr_port | trace_id |
+------+----------+----------------------------------+------+-----------------------------------------------------------------------------------------------------------------+----------------+----------+------------------------------------+
| root | mysql001 | A585F887331EF7267F0C87B343C69D99 | 0s | SELECT USER,
tenant,
sql_id,
concat(time, 's') as time,
info,
svr_ip,
svr_port,
trace_id
FROM GV$OB_PROCESSLIST | 11.xxx.x.xx | 28824 | Y70980BA1CCFB-0006062A332767A6-0-0 |
+------+----------+----------------------------------+------+-----------------------------------------------------------------------------------------------------------------+----------------+----------+------------------------------------+
步骤 2:获取执行计划元数据
通过步骤 1 中获取的 sql_id、svr_ip、svr_port 等信息,查询 GV$OB_PLAN_CACHE_PLAN_STAT 获取该 SQL 的执行计划细节。
SELECT tenant_id, -- 租户 ID
svr_ip, -- 节点 IP
svr_port, -- 节点端口
sql_id, -- SQL 标识
plan_id, -- 执行计划 ID
last_active_time, -- 最后一次执行时间(通常对应慢查询发起时间)
first_load_time, -- 计划首次生成时间
outline_data -- 执行计划的 hint 描述
FROM GV$OB_PLAN_CACHE_PLAN_STAT
WHERE TENANT_ID = 1002
AND SQL_ID = '3310A1D1D81D4BA92CEEF42538136DD1'
AND SVR_IP = '11.xxx.x.xx'
AND SVR_PORT = 35046;
示例输出:
*************************** 1. row ***************************
tenant_id: 1002
svr_ip: 11.xxx.x.xx
svr_port: 35046
sql_id: 3310A1D1D81D4BA92CEEF42538136DD1
plan_id: 741
last_active_time: 2022-08-04 11:00:34.466037
first_load_time: 2022-08-04 11:00:34.466037
outline_data: /*+ BEGIN_OUTLINE_DATA FULL(@"SEL$1" "test.t1"@"SEL$1") END_OUTLINE_DATA*/
输出字段分析:
| 字段 | 作用 |
|---|---|
trace_id |
查询的唯一追踪标识。 |
plan_id |
查询的执行计划的编号。 |
last_active_time |
计划最后一次被使用的时间,通常对应慢查询发起时间。对跑批来说,last_active_time 大概率就是慢查询发起的时间。 |
first_load_time |
执行计划第一次生成的时间。 |
outline_data |
记录优化器生成的 hint,帮助分析计划生成逻辑。 |
步骤 3:获取执行计划细节
通过步骤 2 中的 plan_id,查询 GV$OB_PLAN_CACHE_PLAN_EXPLAIN 获取物理执行计划的树形结构。
SELECT OPERATOR, -- 算子类型
NAME, -- 操作对象
ROWS, -- 预估行数
COST -- 预估成本
FROM GV$OB_PLAN_CACHE_PLAN_EXPLAIN
WHERE TENANT_ID = 1002
AND SVR_IP = '11.xxx.x.xx'
AND SVR_PORT = 35046
AND PLAN_ID = 741;
物理执行计划输出:
+----------------+------+------+------+
| OPERATOR | NAME | ROWS | COST |
+----------------+------+------+------+
| PHY_TABLE_SCAN | t1 | 1 | 45 |
+----------------+------+------+------+
步骤 4:补充逻辑计划分析
若需查看逻辑执行计划,可直接对 SQL 执行 EXPLAIN 命令:
EXPLAIN SELECT SLEEP(1000), RAND() FROM T1;
逻辑计划输出:
Query Plan: ===================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
-----------------------------------
|0 |TABLE SCAN|t1 |1 |46 |
==================================
Outputs & filters:
-------------------------------------
0 - output([sleep(?)], [rand()]), filter(nil),
access([t1.__pk_increment]), partitions(p0)