功能
INFORMATION_SCHEMA.OPERATOR_TRACE 视图用于查询慢查询的算子级执行追踪记录。当查询执行时间超过慢查询阈值且 operator_trace 变量开启时,系统自动收集该查询的完整执行计划树信息(包括每个算子的类型、层级关系、耗时等),写入本地 CSV 日志文件。通过本视图可在线查询历史 trace 记录,辅助定位慢查询根因。该视图基于 DuckDB 实现,通过读取实例数据目录下
operator_trace/ 目录中的 CSV 日志文件返回结果。CSV 字段分隔符为 \\x1F(ASCII Unit Separator),避免与查询数据中的逗号冲突。适用版本
TDSQL Boundless V21.6.4.0及以上版本。
字段说明
字段名 | 类型 | 描述 |
name | VARCHAR(64) | 算子名称,例如 Table scan、Nested loop inner join、Index lookup 等,与 EXPLAIN FORMAT=TREE 输出中的算子名称一致。 |
trace_id | BIGINT UNSIGNED | 该次 trace 的唯一标识 ID。同一次慢查询产生的所有算子记录共享相同的 trace_id。 |
op_id | INT UNSIGNED | 算子在执行计划树中的唯一编号,从0开始递增。 |
parent_id | INT UNSIGNED | 父算子的 op_id。根算子的 parent_id 为0。通过 op_id 和 parent_id 可还原完整的执行计划树结构。 |
start_time | TIMESTAMP | 该算子开始执行的时间戳,精确到毫秒级,带时区信息。 |
duration_ns | BIGINT UNSIGNED | 该算子的执行耗时,单位为纳秒(ns)。 |
extra | JSON | 算子的额外信息,以 JSON 格式存储。包含估计行数( est_rows)、估计代价(est_cost)、实际行数(actual_rows)、循环次数(loops)等运行时统计信息。 |
说明:
extra 字段中的 JSON 内容因算子类型不同而异,常见键包括 est_rows(估计行数)、est_cost(估计代价)、actual_rows(实际行数)、loops(循环次数)等。视图查询前建议先执行
FLUSH OPERATOR_TRACE_LOG 确保内存缓冲区中的日志已刷盘,否则最近写入的 trace 记录可能尚未可见。同一次慢查询产生的多条记录通过相同的
trace_id 关联,结合 op_id 和 parent_id 可还原执行计划树。相关系统变量
变量名 | 级别 | 默认值 | 说明 |
operator_trace | SESSION | OFF | 控制是否对慢查询收集 operator trace。关闭时零性能开销。 |
operator_trace_log_rotate_size | GLOBAL | 104857600(100MB) | 单个 trace 日志文件的大小上限(字节),超出后自动轮转。取值范围:4096 - 1073741824。 |
operator_trace_log_file_count | GLOBAL | 10 | 保留的轮转日志文件数量上限,超出后自动清理最旧文件。 |
示例
# 1. 开启 operator trace 并设置慢查询阈值为 0(确保所有 SQL 都触发收集)SET SESSION operator_trace = ON;SET SESSION long_query_time = 0;# 2. 执行目标查询SELECT * FROM t1 JOIN t2 ON t1.id = t2.id WHERE t1.val > 10;# 3. 刷盘确保日志已写入文件FLUSH OPERATOR_TRACE_LOG;# 4. 查询最近一次慢查询的 operator traceSELECT name, op_id, parent_id, duration_ns, extraFROM information_schema.OPERATOR_TRACEORDER BY trace_id DESC, op_id ASCLIMIT 10;
输出示例:
+-----------------------+-------+-----------+--------------+--------------------------------------------------------------+| name | op_id | parent_id | duration_ns | extra |+-----------------------+-------+-----------+--------------+--------------------------------------------------------------+| Nested loop inner join| 0 | 0 | 12000000 | {"est_rows": 3, "est_cost": 5.2, "actual_rows": 3, "loops": 1} || Filter: (t1.val > 10) | 1 | 0 | 3000000 | {"est_rows": 5, "est_cost": 2.1, "actual_rows": 3, "loops": 1} || Table scan on t1 | 2 | 1 | 5000000 | {"est_rows": 5, "est_cost": 1.0, "actual_rows": 5, "loops": 1} || Index lookup on t2 | 3 | 0 | 8000000 | {"est_rows": 3, "est_cost": 3.1, "actual_rows": 3, "loops": 3} |+-----------------------+-------+-----------+--------------+--------------------------------------------------------------+4 rows in set (0.02 sec)
通过
parent_id 可还原执行计划树结构:根算子 Nested loop inner join(op_id=0)的两个子算子分别为 Filter(op_id=1,parent_id=0)和 Index lookup on t2(op_id=3,parent_id=0),Table scan on t1(op_id=2,parent_id=1)是 Filter 的子算子。