StarRocks Query Detail API 完全指南:通过 FE HTTP 接口获取查询执行明细
【免费下载链接】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
Query Detail API 是 StarRocks FE 提供的一组 HTTP 接口,用于读取缓存于 FE 内存中的近期查询执行明细(QueryDetail),覆盖查询 ID、耗时、扫描行数/字节数、CPU 与内存开销、物化视图来源等维度,是构建查询历史系统、慢查询排查与集群运维监控的常用数据源。本文基于官方文档 docs/en/administration/http_interface/query_detail.md 展开,并结合 FE 端源码(Config.java、QueryDetail.java、QueryDetailQueue.java、QueryDetailAction.java、QueryDetailActionV2.java、StmtExecutor.java)深入讲解接口的调用方式、参数语义、返回字段与底层收集机制,帮助你在实战中直接落地使用。
接口是什么:FE 内存中的查询明细缓存
StarRocks 的每条语句(包括查询与 DDL)在执行时都会在 FE 侧构建一个QueryDetail对象,记录语句的元信息与执行统计。当 FE 配置项enable_collect_query_detail_info为true时,这些QueryDetail记录会被写入 FE 内存中的有界队列(QueryDetailQueue.java),而Query detail API的作用就是通过 HTTP 方式把这些内存缓存读取出来,供外部系统(如 StarRocks Manager 等查询历史/监控组件)轮询拉取。
从源码注释可以看到其设计定位:"It's used to collect queries for monitor"(QueryDetailQueue.java),即该队列本身就是为监控场景准备的。配置项说明也印证了这一点:"StarRocks-manager pull queries every 1 second, metrics calculate query latency every 15 second, do not set cacheTime lower than these time"(Config.java),暗示该接口面向周期性拉取的监控系统设计。
前置条件:开启明细收集
接口能否返回数据,取决于 FE 是否在收集明细。官方文档明确指出:
Query detail records are collected only when the FE configuration
enable_collect_query_detail_infois set totrue.
该配置项定义于 Config.java:
@ConfField(mutable = true) public static boolean enable_collect_query_detail_info = false;关键信息:
- 默认值:
false,即默认不收集; - 是否动态生效(Is mutable):是,无需重启 FE 即可修改;
- 官方参数文档见 log_server_meta.md:设置为
TRUE后系统开始收集查询 profile,设置为FALSE则停止。
有两种方式开启:
-- 方式一:通过 SQL 动态修改(推荐,立即生效) ADMIN SET FRONTEND CONFIG ("enable_collect_query_detail_info" = "true");# 方式二:通过 FE HTTP 接口动态修改 curl -u root: "http://<fe_host>:<fe_http_port>/api/_set_config?enable_collect_query_detail_info=true"由于该配置项mutable = true,修改后无需重启 FE。需要注意:开启后每个 FE 会为每条语句在内存中保留一份QueryDetail,在大并发集群上会带来一定内存与写入开销,建议仅在需要监控/排查时开启。
Endpoints:v1 与 v2 两个版本
接口提供两个版本,均注册于 FE 的 HTTP 服务(默认端口fe_http_port,见 conf/fe.conf 中的http_port,默认 8030):
| 版本 | 路径 | 特点 |
|---|---|---|
| v1 | GET /api/query_detail | 返回裸的 JSON 数组 |
| v2 | GET /api/v2/query_detail | 支持is_request_all_frontend参数,返回包裹结构 |
路由注册代码位于:
- v1:QueryDetailAction.java 中
controller.registerHandler(HttpMethod.GET, "/api/query_detail", ...) - v2:QueryDetailActionV2.java 中
controller.registerHandler(HttpMethod.GET, "/api/v2/query_detail", ...)
请求参数
| 名称 | 必选 | 默认值 | 说明 |
|---|---|---|---|
event_time | 是 | - | 下界过滤条件,仅返回eventTime大于该值的记录;传0可获取当前缓存中的所有记录 |
user | 否 | - | 按user字段过滤,不区分大小写 |
is_request_all_frontend | 否(仅 v2) | false | 为true时,当前 FE 会向集群内其他存活 FE 发起请求并合并结果 |
参数校验逻辑在源码中非常明确:v1 在 QueryDetailAction.java 中,event_time缺失时直接返回not valid parameter与 HTTP 400;v2 在 QueryDetailActionV2.java 中做了同样的空值校验。
event_time的语义需要特别理解:它对应的不是查询开始时间startTime,而是记录被写入队列时生成的单调递增纳秒时间戳eventTime。由于查询开始时会先入队一条RUNNING状态的记录,结束时更新该记录并再次入队(见下文"生命周期"一节),因此用eventTime做增量拉取(incremental pull)是安全的,不会遗漏状态更新。
响应格式
v1直接返回一个QueryDetail对象的 JSON 数组:
[ { "queryId": "9fc7108f-...", "eventTime": 1753671088000000000, ... } ]v2返回统一的包裹结构:
{ "code": "0", "message": "OK", "result": [ { "queryId": "9fc7108f-...", ... } ] }其中result为QueryDetail列表。v2 的包裹结构定义于 RestBaseResultV2(同目录下),构造与序列化逻辑见 QueryDetailActionV2.java。
认证与授权
该接口要求HTTP Basic 认证:即请求必须携带合法用户名/密码(如-u root:),认证通过即可访问,没有额外的权限校验。也就是说,任何通过认证的用户都能读取全部缓存的查询明细,除非通过user参数做了过滤。这一点在 v1 与 v2 的实现中都通过requireOperateIfHttpAuthEnabled()(QueryDetailAction.java、QueryDetailActionV2.java)保证。
由于接口可能暴露任意用户的 SQL 文本,在生产环境建议:仅在可信内网开放 FE HTTP 端口,或将enable_collect_query_detail_info保持关闭、按需临时开启。
QueryDetail 字段详解
QueryDetail类定义于 QueryDetail.java,字段与官方文档一一对应。以下是完整字段表:
| 字段 | 类型 | 说明 |
|---|---|---|
queryId | string | 查询 ID |
eventTime | long | 内部时间戳,用于过滤;由墙钟时间派生的单调纳秒时间戳 |
isQuery | boolean | 语句是否为查询 |
remoteIP | string | 客户端 IP,非客户端请求时为System |
connId | int | 连接 ID |
startTime | long | 查询开始时间,Unix 毫秒时间戳 |
endTime | long | 查询结束时间,Unix 毫秒时间戳;未完成时为-1 |
latency | long | 查询延迟,毫秒;未完成时为-1 |
pendingTime | long | 排队等待时间,毫秒 |
netTime | long | 净执行时间,毫秒 |
netComputeTime | long | 净计算时间,毫秒 |
state | string | 状态之一:RUNNING、FINISHED、FAILED、CANCELLED |
database | string | 当前数据库 |
sql | string | SQL 文本(如配置了脱敏则可能为脱敏文本) |
user | string | 登录用户(qualified user) |
impersonatedUser | string | EXECUTE AS的目标用户;未模拟其他用户时为null |
errorMessage | string | 失败时的错误信息 |
explain | string | Explain 计划(详细程度由query_detail_explain_level控制) |
profile | string | 已收集时的 Profile 文本 |
resourceGroupName | string | 资源组名称 |
scanRows | long | 扫描行数 |
scanBytes | long | 扫描字节数 |
returnRows | long | 返回行数 |
cpuCostNs | long | CPU 开销,纳秒 |
memCostBytes | long | 内存开销,字节 |
spillBytes | long | 落盘字节数 |
cacheMissRatio | float | 缓存未命中率,百分比(0-100) |
warehouse | string | Warehouse 名称 |
digest | string | SQL digest |
catalog | string | Catalog 名称 |
command | string | MySQL 命令名称 |
preparedStmtId | string | 预编译语句 ID |
queryFeMemory | long | 该查询在 FE 侧分配的内存,字节 |
querySource | string | 查询来源:EXTERNAL、INTERNAL、MV、TASK |
几个值得展开的字段:
state对应源码中的枚举QueryMemState(QueryDetail.java),四个状态值与文档一致。
querySource对应枚举QuerySource(QueryDetail.java):
EXTERNAL:用户发起的查询;INTERNAL:系统/内部查询;MV:物化视图刷新产生的语句;TASK:任务提交的查询。
该字段可帮助你在过滤监控数据时区分用户流量与系统内部流量,例如排除INTERNAL与MV以免干扰慢查询统计。注意 StmtExecutor.java 中,当语句实际由内部逻辑触发时会从EXTERNAL改写为INTERNAL。
cacheMissRatio由calculateCacheMissRatio(readLocalCnt, readRemoteCnt)计算(QueryDetail.java):(readRemoteCnt * 100) / (readLocalCnt + readRemoteCnt),读远程块的比例越高,缓存命中率越低。当总读取数为 0 时为 0。
sql的脱敏行为:在 StmtExecutor.java 中,当语句需要加密(AuditEncryptionChecker.needEncrypt)或enable_sql_desensitize_in_log开启时,SQL 会被重建为脱敏文本;否则若 SQL 含凭据关键词(如密码),会通过SqlCredentialRedactor.redact做凭据遮蔽。因此 API 返回的sql不一定是原始文本。
database的处理:构造 QueryDetail 时如果数据库名形如cluster:db(带 cluster 前缀),会截取冒号后的部分(QueryDetail.java)。
记录的收集生命周期:从入队到过期
理解接口返回的数据形态,需要知道QueryDetail是如何被写入和更新的。核心流程在 StmtExecutor.java 的两个方法中:
查询开始时——
addRunningQueryDetail(parsedStmt)(L4222-L4281):- 若
enable_collect_query_detail_info为false直接返回; - 构造
QueryDetail,填入 queryId、isQuery、remoteIP、connId、startTime、database、sql、user、resourceGroupName、warehouse、catalog、command、preparedStmtId,状态置为RUNNING; - 通过
QueryDetailQueue.addQueryDetail(queryDetail.copy())入队(注意这里入队的是copy,因为后续属性会变化)。
- 若
查询结束时——
addFinishedQueryDetail()(L4294-L4345):- 计算
endTime、latency(endTime - startTime)、queryFeMemory(线程分配内存差值); - 根据执行状态设置
FINISHED或FAILED(失败时写入errorMessage); - 填充
pendingTime、netTime、netComputeTime; - 从执行统计
PQueryStatistics填充scanRows、scanBytes、cpuCostNs、memCostBytes、spillBytes、returnRows、digest,并计算cacheMissRatio; - 再次入队(更新后的完整记录)。
- 计算
队列管理——QueryDetailQueue.java:
- 内部为无界并发双端队列
ConcurrentLinkedDeque<QueryDetail>(L52); - 每 5 秒由单线程调度器执行一次
removeExpiredQueryDetails()(L58-L60),删除eventTime早于当前纳秒时间 - query_detail_cache_time_nanosecond的记录; eventTime由getCurrentTimeNS()生成(L122-L131):同一毫秒内的多条记录会通过自增计数保证时间戳严格单调递增,避免过滤时出现边界丢失。
缓存时长配置——query_detail_cache_time_nanosecond(Config.java):
- 默认值:
30000000000(即 30 秒,单位纳秒); - 可动态修改(
mutable = true); - 源码注释建议不要设低于 1 秒(StarRocks Manager 每 1 秒拉取)或 15 秒(metrics 每 15 秒计算延迟)。
Explain 级别配置——query_detail_explain_level(Config.java):
- 默认值:
COSTS; - 可动态修改;控制返回记录中
explain字段的详细程度,调整后可通过ADMIN SET FRONTEND CONFIG ("query_detail_explain_level" = "NORMAL");或EXTENDED等取值来平衡信息量与开销。
SQL digest 配置——enable_sql_digest(Config.java):开启后为每条 SQL 生成参数化的 digest 写入digest字段,便于按 SQL 形态聚合统计。
使用示例
v1:获取当前缓存的所有查询明细
curl -u root: "http://<fe_host>:<fe_http_port>/api/query_detail?event_time=0"v2:增量拉取并聚合所有 FE
curl -u root: "http://<fe_host>:<fe_http_port>/api/v2/query_detail?event_time=0&is_request_all_frontend=true"v2:按用户过滤
curl -u root: "http://<fe_host>:<fe_http_port>/api/v2/query_detail?event_time=1753671088&user=root"其中user过滤在 QueryDetailQueue.java 中实现为queryDetail.getUser().equalsIgnoreCase(user),即不区分大小写匹配。
增量拉取的正确姿势:监控程序应当记录上次拉取返回记录中的最大eventTime,下次以该值为event_time继续拉取,从而避免重复与遗漏。由于队列中同一查询会以RUNNING和终态两条记录先后出现(两条记录的eventTime不同),增量拉取天然能拿到"先 RUNNING 后 FINISHED/FAILED"的完整状态流转。
v2 全 FE 聚合的实现原理(QueryDetailActionV2.java):当is_request_all_frontend=true时,当前 FE 会构造同样的请求路径(保留event_time与user参数),携带当前认证信息,通过fetchResultFromOtherFrontendNodes向集群内其他存活 FE 发起并行请求,再以GsonUtils反序列化各 FE 返回的RestBaseResultV2<List<QueryDetail>>并合并到结果集中返回。这在多 FE 集群中省去了逐个节点请求的麻烦。
典型应用场景
- 构建查询历史系统:周期性调用 v2 接口增量拉取全集群查询明细,落库后支持按用户、SQL、耗时、扫描量检索与审计;
- 慢查询定位:用
latency、pendingTime、netTime与netComputeTime拆分延迟构成,判断瓶颈在排队、解析规划还是执行阶段; - 资源开销分析:结合
cpuCostNs、memCostBytes、spillBytes、scanBytes、queryFeMemory评估大查询与落盘行为,辅助资源组与 Warehouse 规划; - 缓存效果观察:
cacheMissRatio可用于评估数据缓存命中情况; - 故障复盘:
FAILED状态记录携带errorMessage,explain与profile字段可用于分析执行计划与性能 Profile。
相关资源
- 接口官方文档:query_detail.md
- HTTP 接口总览(FE 接口清单,其中列出了
/api/query_detail):http_interface.md - FE 配置参数说明(
enable_collect_query_detail_info等):log_server_meta.md - 接口实现:QueryDetailAction.java、QueryDetailActionV2.java
- 数据模型与队列:QueryDetail.java、QueryDetailQueue.java
- 明细写入入口:StmtExecutor.java
- 配置定义:Config.java
需要注意的是,本文所述端口、路径与配置取值均以当前仓库代码与文档为准;不同 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),仅供参考