ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

StarRocks last_query_id 函数详解:如何获取当前会话中最近一次查询的 Query ID

StarRocks last_query_id 函数详解:如何获取当前会话中最近一次查询的 Query ID StarRocks last_query_id 函数详解如何获取当前会话中最近一次查询的 Query ID【免费下载链接】starrocksThe worlds 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本文基于 StarRocks 官方 SQL 函数参考文档 last_query_id.md 编写并深入当前仓库的 FE前端与 BE后端源码进行印证与扩充。导读last_query_id()是 StarRocks 提供的一个零参数工具函数用于获取当前会话中最近一次成功执行完毕的查询的 Query ID。这个 ID 是全局唯一的 UUID 字符串可用来在 StarRocks 中对查询进行精确的定位、追踪与事后分析例如配合 Profile 分析定位慢查询、在日志与监控系统中关联具体查询、审计特定 SQL 的执行记录。读完本文你将掌握last_query_id()的完整语法与语义、真实使用示例以及它在 FE 与 BE 两侧的底层实现原理和注意事项。函数概述从会话中追溯上一条查询在数据库运维与开发场景中拿到上一条查询的标识是一项非常实用的能力Profile 关联分析执行某条耗时 SQL 后立即用last_query_id()取回其 Query ID用于查询执行计划与 Profile 分析问题追踪Query ID 会被写入 StarRocks 的日志、审计与监控链路拿到 ID 即可跨模块串联该查询的完整执行轨迹精确管理结合会话上下文能区分当前正在执行的查询与刚执行完的查询。last_query_id()正是为这类场景设计的——它返回的是上一个已完成查询的 ID而不是当前正在执行的这条查询的 ID获取当前查询 ID 请使用query_id()。语法与语义根据官方文档last_query_id()的完整语法如下VARCHAR last_query_id();关键语义要点项目说明函数名last_query_id大小写不敏感文档关键词为LAST_QUERY_ID参数无括号内必须为空返回值类型VARCHAR返回值内容当前会话最近一次执行的查询的 Query ID形如7c1d8d68-bbec-11ec-af65-00163e1e238f的 UUID 字符串空值行为若当前会话中尚不存在已完成的查询则返回NULL下文源码部分会详细印证参数说明该函数不接受任何参数调用时直接写SELECT last_query_id();即可。返回值说明返回VARCHAR类型值为标准 UUID 格式8-4-4-4-12的 36 字符形式例如7c1d8d68-bbec-11ec-af65-00163e1e238f当会话中还没有上一次查询时返回NULL。使用示例官方文档给出的基准示例mysql select last_query_id(); -------------------------------------- | last_query_id() | -------------------------------------- | 7c1d8d68-bbec-11ec-af65-00163e1e238f | -------------------------------------- 1 row in set (0.00 sec)在该示例中last_query_id()返回了7c1d8d68-bbec-11ec-af65-00163e1e238f——这正是该会话中上一条查询的 Query ID。基于此可以进一步扩展出几种实战用法用法一先执行业务查询再立即取回其 Query IDmysql SELECT COUNT(*) FROM lineorder WHERE lo_discount 90; ---------- | count(*) | ---------- | 290091 | ---------- 1 row in set (0.10 sec) mysql SELECT last_query_id() AS qid; -------------------------------------- | qid | -------------------------------------- | 3f5b1c2a-7d9e-4a10-b2c3-d4e5f6a7b8c9 | -------------------------------------- 1 row in set (0.00 sec)用法二将 Query ID 保存到会话变量中供后续分析使用mysql SET prev_qid last_query_id(); mysql SELECT prev_qid;用法三与ANALYZE PROFILE配合从源码看last_query_id的更新逻辑特意跳过了AnalyzeProfileStmt说明两者经常搭配使用——先用普通查询拿到 ID再用ANALYZE PROFILE query_id分析该查询的 Profile见下文底层实现原理部分。底层实现原理FE 与 BE 两侧的完整调用链last_query_id()看似简单实则横跨 StarRocks 的 FE元数据与调度与 BE执行引擎两层。以下结合当前仓库源码逐步拆解。1. FE 端会话上下文中维护上一条查询 ID在 FE 侧last_query_id被定义为一个元函数meta function实现在 MetaFunctions.java/** * Return the query ID of the last executed query in the current session. */ ConstantFunction(name last_query_id, argTypes {}, returnType VARCHAR, isMetaFunction true) public static ConstantOperator lastQueryId() { ConnectContext connectContext ConnectContext.get(); if (connectContext null) { return ConstantOperator.createNull(VarcharType.VARCHAR); } UUID lastQueryId connectContext.getLastQueryId(); if (lastQueryId null) { return ConstantOperator.createNull(VarcharType.VARCHAR); } return ConstantOperator.createVarchar(lastQueryId.toString()); }从源码可以确认三个事实该函数是无参数常量函数返回值类型为VARCHAR注册名称为last_query_id对应 FunctionSet.java 中的函数注册数据来源是当前会话上下文ConnectContext.get()中的lastQueryId字段当会话上下文不存在或lastQueryId尚未被赋值即会话中还没有执行完任何查询时函数返回NULL——这与本文返回值说明中的空值行为完全一致。lastQueryId字段定义于 ConnectContext.javaprotected UUID lastQueryId;并提供了标准的 getter/setterConnectContext.java#L1042-L1048。2. FE 端Query ID 何时被沉淀为 Last Query ID关键在于 ConnectProcessor.java它在一次查询命令处理完成后更新会话状态// only change lastQueryId when current command is COM_QUERY MysqlCommand cmd ctx.getCommand(); if (cmd MysqlCommand.COM_QUERY || cmd MysqlCommand.COM_STMT_PREPARE || cmd MysqlCommand.COM_STMT_EXECUTE) { boolean skipSetLastQueryId executor ! null executor.getParsedStmt() instanceof com.starrocks.sql.ast.AnalyzeProfileStmt; if (!skipSetLastQueryId) { ctx.setLastQueryId(ctx.getQueryId()); } ctx.setQueryId(null); }这段代码揭示了几条重要语义更新时机只有当本次命令是COM_QUERY、COM_STMT_PREPARE或COM_STMT_EXECUTE即真正的查询类命令时才会把当前查询的queryId记录为会话的lastQueryId其他命令如COM_PING、COM_INIT_DB等不会更新它ANALYZE PROFILE特例当本次执行的是AnalyzeProfileStmt即用户正在分析某条查询的 Profile时不会更新lastQueryId。可以推断这是为了避免分析 Profile 的这条查询覆盖掉用户真正想追踪的那条查询的 ID会话隔离lastQueryId保存在ConnectContext会话上下文中因此它是会话级的不同会话之间互不影响执行语义该更新发生在查询执行完成、结果包发送完毕之后因此lastQueryId恒指最近一次执行完毕的查询而不是正在执行的查询。3. BE 端执行引擎中的实现在 BE 侧last_query_id作为工具函数Utility Function实现函数声明位于 utility_functions.hDEFINE_VECTORIZED_FN(last_query_id);与其相邻的还有query_id返回当前查询 ID、uuid、sleep、version等常用工具函数函数实现位于 utility_functions.cppStatusOrColumnPtr UtilityFunctions::last_query_id(FunctionContext* context, const Columns columns) { starrocks::RuntimeState* state context-state(); const std::string id state-last_query_id(); if (!id.empty()) { return ColumnHelper::create_const_columnTYPE_VARCHAR(id, 1); } else { return ColumnHelper::create_const_null_column(1); } }对应地RuntimeState中保存了该字段并在构造函数中初始化字段定义与访问器runtime_state.h#L174const std::string last_query_id() const与 runtime_state.h#L688std::string _last_query_id;赋值来源runtime_state.cpp#L187-L189if (query_globals.__isset.last_query_id) { _last_query_id query_globals.last_query_id; }也就是说BE 端的_last_query_id来自 FE 下发的query_globals.last_query_id查询全局信息与 FE 会话上下文中的lastQueryId保持一致若下发值为空BE 端同样返回NULL列。4. 完整调用链小结客户端执行查询 │ ▼ FE: ConnectProcessor 处理 COM_QUERY/COM_STMT_PREPARE/COM_STMT_EXECUTE │ 执行完毕后 ctx.setLastQueryId(ctx.getQueryId()) ▼ FE: 下一次查询解析时last_query_id() 作为 meta function │ 从 ConnectContext.getLastQueryId() 取值null 则返回 NULL ▼ BE: FE 将 query_globals.last_query_id 下发给执行引擎 │ RuntimeState::_last_query_id 保存该值 ▼ BE: UtilityFunctions::last_query_id() 从 RuntimeState 读取并返回 VARCHAR使用注意事项结合官方文档与源码实现使用last_query_id()时有几点需要留意会话级语义它返回的是当前会话中最近一次执行的查询 ID。新建会话后第一次调用last_query_id()会得到NULL因为会话中还没有执行完任何查询上一次而非当前在一条查询内部调用它得到的仍是该查询之前的最后一条查询 ID而不是它自身需要当前查询自身 ID 时应使用query_id()空值处理当会话中没有可用的上一次查询 ID 时函数返回NULL业务侧需做判空处理命令类型限制只有查询类命令COM_QUERY、COM_STMT_PREPARE、COM_STMT_EXECUTE会刷新lastQueryId且ANALYZE PROFILE语句不会刷新它典型组合场景SELECT last_query_id();之后可配合ANALYZE PROFILE query_id、日志审计或监控系统将 Query ID 作为查询全链路追踪的锚点。与相关函数的对比函数返回内容典型用途last_query_id()当前会话最近一次已执行完毕查询的 Query ID回溯上一条查询配合 Profile/审计分析query_id()当前正在执行查询的 Query IDutility_functions.h#L41-L43 中声明BE 端若hi/lo均为 0 则返回NULL获取本条查询自身的 IDuuid()/uuid_numeric()会话内生成的 UUID生成唯一标识不依赖查询上下文三者同为 StarRocks 的工具类Utility函数族均位于 utility_functions.h 与 utility_functions.cpp 中。深入阅读官方函数参考last_query_id.md含中、日文版本于 docs/zh、docs/jaFE 端元函数实现MetaFunctions.javaFE 端会话上下文ConnectContext.javalastQueryId字段与 ConnectProcessor.java更新时机BE 端执行实现utility_functions.cpp 与 runtime_state.cpp相关工具函数query_id、uuid等的完整列表见 utility_functions.h【免费下载链接】starrocksThe worlds 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),仅供参考
返回列表