StarRocks ANALYZE PROFILE 详解:基于 Query Profile 的树形执行分析
【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks
ANALYZE PROFILE 是 StarRocks(v3.1 起)提供的一条专用 SQL 语句,用于以 Fragment(执行片段)为单位、以树形结构分析指定查询的 Query Profile,帮助开发者从执行计划层面快速定位慢查询瓶颈。本文将完整讲解该语句的语法、参数、输出结构、底层实现原理,并结合仓库源码与配套语句(SHOW PROFILELIST、EXPLAIN ANALYZE)给出可复用的调优工作流。
功能概述
Query Profile 记录了查询执行过程中所有工作节点的执行信息,是 StarRocks 诊断与调优查询性能的强有力工具。而 Query Profile 概述 中介绍的各种 Profile 获取方式(Web UI、get_query_profile()函数等)返回的都是原始文本,人工阅读成本较高。
ANALYZE PROFILE 则对指定查询的 Profile 做结构化再加工:
- 以Fragment 为单位组织展示:每个 Fragment 下的计划节点(Plan Node)及其指标被整理成树形结构,符合执行计划本身的层级关系;
- 支持按需下钻:指定
plan_node_id后,可查看该节点的详细指标,并对使用占比较高的指标做高亮,便于快速定位热点; - 对已结束或正在运行的查询均可分析:只要该查询的 Profile 仍缓存在 FE 内存中,就可以用
query_id随时回溯。
需要说明的是,ANALYZE PROFILE 本身不执行任何 SQL,它只读取已存在的 Profile 快照并格式化输出,因此成本极低,适合作为慢查询复盘的标准动作。
权限要求
注意
只有对特定表拥有SELECT 权限的用户才能执行此操作。
该限制与SHOW PROFILELIST(无需权限)不同,与EXPLAIN ANALYZE(需要 SELECT 或 INSERT 权限)相近。从权限设计可以推断,ANALYZE PROFILE 的 Profile 内容可能涉及表的执行细节(扫描行数、谓词、分区裁剪等),因此 StarRocks 将其视为对表数据的间接访问,要求最小化权限授权。
语法与参数
语法
ANALYZE PROFILE FROM '<query_id>', [<plan_node_id>[, ...] ]参数说明
| 参数 | 说明 |
|---|---|
query_id | 查询 ID。可以通过 SHOW PROFILELIST 获得。 |
plan_node_id | Query Profile 中的计划节点 ID。指定后可查看对应计划节点的详细指标;若不指定,则仅显示所有计划节点的摘要指标。 |
参数细节说明
query_id是字符串,语法上需要用单引号包裹,例如ANALYZE PROFILE FROM 'a40456b2-8428-11ee-8d02-6a32f8c68848';plan_node_id是整数,多个节点 ID 用逗号分隔,例如ANALYZE PROFILE FROM 'query_id', 0, 1, 2;- 若要查看整棵执行计划树的详细指标,可依次对每个 Fragment 下的关键节点执行 ANALYZE PROFILE。
从 StarRocks.g4 的语法定义看,该语句还额外支持LAST_QUERY_ID()简写形式:
analyzeProfileStatement : ANALYZE PROFILE FROM string | ANALYZE PROFILE FROM string ',' INTEGER_VALUE (',' INTEGER_VALUE)* | ANALYZE PROFILE FROM LAST_QUERY_ID '(' ')' | ANALYZE PROFILE FROM LAST_QUERY_ID '(' ')' ',' INTEGER_VALUE (',' INTEGER_VALUE)*即:
-- 直接分析当前会话最近一次查询的 Profile ANALYZE PROFILE FROM LAST_QUERY_ID(); -- 分析最近一次查询中节点 0、1 的详细指标 ANALYZE PROFILE FROM LAST_QUERY_ID(), 0, 1;AnalyzeProfileParserTest.java 中的用例(如ANALYZE PROFILE FROM 'test-query-id', 1, 2, 3、ANALYZE PROFILE FROM LAST_QUERY_ID(), 0, 1)印证了上述两种语法的解析路径。
输出结构详解
ANALYZE PROFILE 的输出由 ExplainAnalyzer.analyze() 生成,由两个主要部分构成:
Summary(概要)
概要部分包含以下信息:
- QueryID:查询 ID,与
SHOW PROFILELIST中展示的 ID 一致; - 版本信息:产生该 Profile 的 StarRocks 版本;
- 查询状态:
Finished、Error、Running三种之一; - 总查询耗时;
- 内存使用情况;
- CPU 使用率最高的 Top 10 节点;
- 内存使用最高的 Top 10 节点;
- 与会话默认值不同的 Session 变量:这部分在排查"为什么这个查询这么慢"时非常有用,例如
pipeline_dop、parallel_fragment_exec_instance_num等被修改过的变量会在这里列出。
Fragments(各 Fragment 指标)
- 展示每个 Fragment 中各节点的时间、内存使用、代价估算信息与输出行数;
- 时间占比超过 30% 的节点会以红色高亮;
- 时间占比超过 15% 且低于 30% 的节点会以粉色高亮。
高亮机制是本功能的核心价值:无需逐行比对指标,热点节点在视觉上一目了然。在 Query Profile 文本化分析 中对此有更详细的说明。
指定节点 ID 时的输出差异
- 不指定
plan_node_id:只展示各节点的摘要指标(时间、内存、输出行数等),用于快速定位"哪个节点最慢"; - 指定
plan_node_id:输出该节点对应的全部详细指标(输入输出行数、CPU 时间、内存、各类执行时间细分等),并高亮使用占比较高的指标,用于深入分析"这个节点为什么慢"。
底层实现原理
从 FE 源码可以还原 ANALYZE PROFILE 的完整调用链:
- 语法解析:
AstBuilder根据 StarRocks.g4 将语句构建为 AnalyzeProfileStmt,其中保存queryId与planNodeIds两个字段; - 执行入口:
StmtExecutor判断parsedStmt instanceof AnalyzeProfileStmt后进入handleAnalyzeProfileStmt(); - Profile 查找:通过
ProfileManager.getInstance().getProfileElement(queryId)从 FE 内存中取出缓存的 Profile;若找不到,会抛出异常"Query profile not found for query_id: ... The query may have been evicted from memory."——这意味着 Profile 的保留时间有限,建议在查询结束后尽早分析; - 格式转换:调用
ExplainAnalyzer.analyze(profileElement.plan, profileElement.getRuntimeProfile(), planNodeIds, ...)将 RuntimeProfile 结合执行计划plan渲染成带高亮的树形文本。
边界情况
- 短路径查询(Short Circuit):源码中对
ProfileElement#plan == null且查询类型非 Load 的情况会直接报错,提示可用SET enable_short_circuit = false关闭短路径后再分析。这说明短路径点查(如主键点查)不生成完整执行计划,无法用 ANALYZE PROFILE 分析; - Profile 已失效:如果 Profile 被移出内存(例如查询时间久远),语句会报错,需要重新执行查询并尽快分析。
获取 query_id 的配套语句
SHOW PROFILELIST
执行 ANALYZE PROFILE 前,需要先通过 SHOW PROFILELIST 获取目标查询的 ID:
SHOW PROFILELIST [LIMIT n];其中LIMIT n用于列出最近 n 条记录。返回字段如下:
| 返回列 | 说明 |
|---|---|
| QueryId | 查询 ID,供 ANALYZE PROFILE 使用。 |
| StartTime | 查询开始时间。 |
| Time | 查询延迟。 |
| State | 查询状态:Error(出错)、Finished(完成)、Running(运行中)。 |
| Statement | 查询语句内容。 |
示例:
SHOW PROFILELIST LIMIT 5;输出形如:
+--------------------------------------+---------------------+-------+----------+-------------------------------------+ | QueryId | StartTime | Time | State | Statement | +--------------------------------------+---------------------+-------+----------+-------------------------------------+ | a40456b2-8428-11ee-8d02-6a32f8c68848 | 2023-11-16 10:34:18 | 21ms | Finished | SELECT ROUTINE_NAME FROM ... | | a26ec286-8428-11ee-8d02-6a32f8c68848 | 2023-11-16 10:34:15 | 269ms | Error | EXPLAIN ANALYZE SELECT c_nation ... | +--------------------------------------+---------------------+-------+----------+-------------------------------------+该语句无需任何权限,且能列出运行中超过 10 秒的查询——这意味着你可以对慢到还没结束的查询直接分析其 Runtime Query Profile。
last_query_id() 与 get_query_profile()
last_query_id():返回当前会话最近一次执行的查询 ID,配合ANALYZE PROFILE FROM LAST_QUERY_ID()可省去手动复制 ID 的步骤;get_query_profile('<query_id>'):以 SQL 函数形式返回指定查询的原始文本 Profile,适合脚本化抓取。
完整工作流示例(参考 Query Profile 概述):
SET enable_profile = true; -- 执行一个包含扫描与聚合的查询以产生有意义的 Profile SELECT count(*) FROM information_schema.columns; -- 获取该查询的 query_id SELECT last_query_id(); +--------------------------------------+ | last_query_id() | +--------------------------------------+ | 019b364f-10c4-704c-b79a-af2cc3a77b89 | +--------------------------------------+ -- 查看 Profile 列表 SHOW PROFILELIST; -- 结构化分析 Profile(树形展示) ANALYZE PROFILE FROM '019b364f-10c4-704c-b79a-af2cc3a77b89'; -- 下钻到节点 0 的详细指标 ANALYZE PROFILE FROM '019b364f-10c4-704c-b79a-af2cc3a77b89', 0;使用示例
示例一:不指定节点 ID,查看整棵执行树的摘要。
输出按 Fragment 组织,每个节点展示时间、内存、输出行数等摘要指标;时间占比超过 30% 的节点以红色高亮、15%~30% 的以粉色高亮,热点一目了然。
示例二:指定节点 ID 为 0,查看该节点的全部详细指标。
StarRocks 返回 Node ID 为0的所有详细指标,并高亮使用占比较高的指标,便于定位该节点内部的瓶颈。
使用建议
- 先摘要后下钻:先执行不带
plan_node_id的语句确定热点节点,再针对热点节点指定 ID 查看细节,避免信息过载; - 关注 Summary 的会话变量差异:被修改过的 Session 变量往往是"非预期慢"的元凶;
- 分析运行中的查询:当查询卡住超过 10 秒时,可先用
SHOW PROFILELIST找到Running状态的查询,再对其执行 ANALYZE PROFILE,此时输出中会包含算子状态(⏳ 未开始、🚀 运行中、✅ 已完成)与整体/算子级进度信息; - 注意客户端兼容性:输出文本包含 ANSI 颜色字符,推荐使用 MyCLI 客户端;使用不支持 ANSI 的客户端(如部分 MySQL 客户端)可能出现轻微排版错乱,通常不影响阅读。
与 EXPLAIN ANALYZE 的分工
EXPLAIN ANALYZE 与 ANALYZE PROFILE 是互补的两条语句:
| 维度 | ANALYZE PROFILE | EXPLAIN ANALYZE |
|---|---|---|
| 是否执行 SQL | 否,仅分析已有 Profile | 是,执行并生成新 Profile |
| 适用对象 | 历史/运行中的任意查询(含他人发起的) | 当前会话将要执行的 SELECT / INSERT INTO 语句 |
| 权限要求 | 目标表的 SELECT 权限 | 目标表的 SELECT 或 INSERT 权限 |
| 典型场景 | 慢查询复盘、生产问题回溯 | 上线前模拟验证、对比改写前后的执行效果 |
EXPLAIN ANALYZE 的语法:
EXPLAIN ANALYZE <statement>;注意两点使用限制:
- 支持 SELECT 与 INSERT INTO 两类语句,但INSERT INTO 的 Profile 分析仅支持默认 Catalog 下的内表,且分析过程中不会真正写入数据——导入事务默认会被中止,确保分析过程不产生数据变更;
- 执行
EXPLAIN ANALYZE时,StarRocks 会默认在当前会话开启 Query Profile 功能。
前置条件:确保 Profile 可用
ANALYZE PROFILE 依赖 FE 内存中缓存的 Profile,因此分析前需确保对应查询已生成 Profile:
- 开启 Profile:
SET enable_profile = true; -- 仅当前会话 SET GLOBAL enable_profile = true; -- 全局生效(生产环境不建议长期开启)- 只捕获慢查询(推荐的生产姿势):设置
big_query_profile_threshold,只对超过阈值的查询生成 Profile,避免全局开启带来的额外开销:
SET global big_query_profile_threshold = '30s'; -- 30 秒 SET global big_query_profile_threshold = '500ms'; -- 500 毫秒 SET global big_query_profile_threshold = '60m'; -- 60 分钟- 及时分析:Profile 在 FE 内存中缓存,被淘汰后将无法用 ANALYZE PROFILE 回溯,请在查询结束后尽快执行。
相关文档
- SHOW PROFILELIST:获取查询 ID 列表
- EXPLAIN ANALYZE:模拟执行并分析新查询的 Profile
- Query Profile 概述:Profile 的开启、获取与整体解读
- Query Profile 文本化分析:ANALYZE PROFILE 输出结构的深度解读
- Query Profile 算子指标:各算子的指标含义
总结
ANALYZE PROFILE 是 StarRocks 查询调优链路中连接"Profile 采集"与"瓶颈定位"的关键一环:通过SHOW PROFILELIST拿到query_id,用ANALYZE PROFILE以 Fragment 为单位的树形结构快速锁定热点节点,再配合plan_node_id下钻与EXPLAIN ANALYZE验证优化效果,即可形成"定位 → 下钻 → 验证"的完整闭环。其输出中的红色/粉色高亮、Summary 会话变量差异、以及运行中查询的进度展示,都极大降低了慢查询分析的门槛,是从 v3.1 起每个 StarRocks 开发者都应掌握的基础调优手段。
【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考