新闻详情

新闻详情

首页 / 资讯中心 / 详情

StarRocks 字典表达式扩展模块(ExprDict)深入解析:模块边界、核心实现与执行原理

发布时间:2026/9/15 19:11:28来源:尧图网络
StarRocks 字典表达式扩展模块(ExprDict)深入解析:模块边界、核心实现与执行原理
StarRocks 字典表达式扩展模块ExprDict深入解析模块边界、核心实现与执行原理【免费下载链接】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 仓库中 be/src/exprs_ext/dict/AGENTS.md 模块说明文档为骨架结合be/src/exprs_ext/dict/目录下的源码实现系统讲解后端BE字典表达式扩展模块ExprDict的职责边界、依赖规则、工厂注册机制以及DictMappingExpr、DictQueryExpr、DictionaryGetExpr、dict_encode四类字典相关表达式从open到evaluate_checked的完整执行链路。读者读完本文将掌握StarRocks 全局字典优化与字典缓存功能在后端是如何落地为具体表达式节点的、各节点与Expr/ComputeEnv/Storage等底层模块的协作关系以及新增字典表达式时应当遵守的模块边界约束。一、模块定位什么是 ExprDictbe/src/exprs_ext/dict/目录对应 BE 模块清单be/module_boundary_manifest.json中 id 为exprdict、doc_label 为ExprDict的模块。官方摘要对其职责的定义是Dictionary expression extensions and dict expression factory registration above Expr, ComputeEnv, and Storage integration.即建立在Expr、ComputeEnv、Storage之上的字典表达式扩展以及字典表达式的工厂注册逻辑。它属于 StarRocks 后端exprs_ext表达式扩展体系的一部分与exprs_ext/dict平级的扩展目录还包括 table function 等扩展其共同点是在核心表达式基础设施之上提供需要具体存储/计算环境支撑的高级表达式能力。从模块边界清单可以看到该模块的完整约束be/module_boundary_manifest.json维度内容模块 id / 标签exprdict/ExprDict模块文档be/src/exprs_ext/dict/AGENTS.md拥有的构建目标ExprDict允许的内部 include 前缀exprs_ext/dict/、exprs/、compute_env/、storage/、storage_primitive/、exec/exec_env.h、platform/、runtime/、column/、types/、common/、base/、gutil/、gen_cpp/允许依赖的构建目标Expr、ComputeEnv、Storage、StoragePrimitive、Exec、Platform、Runtime、ColumnSortCore、ChunkCore、ColumnCore、Types、Common、Base、Gutil、StarRocksGen禁止 include 前缀service/、http/、agent/、connector/这一边界约束的含义可以归纳为两点向上依赖受限字典表达式可以自由依赖列/Chunk/Types 等底层基础设施column/、types/、base/等、表达式基础设施exprs/、计算环境compute_env/与存储storage/、storage_primitive/但不能反向侵入service/、http/、agent/、connector/等服务层与连接器层从而保证扩展模块的可复用性与可测试性。职责划分清晰如 AGENTS.md 中 remediation 条款所述——字典专属的表达式实现应放在 ExprDict 内共享的表达式契约应归属 Expr 模块更上层的查询执行编排query execution orchestration应位于扩展层之上。换言之ExprDict 是薄薄的一层字典专用适配负责把字典语义翻译成底层ExprComputeEnvStorage可以执行的形式。二、目录结构与源码全景be/src/exprs_ext/dict/下共有 9 个文件按职责可分为四组文件职责expr_factory_dict_exprs_extension.cpp表达式工厂注册通过ExprFactory::set_non_core_create_post_hook挂钩三类字典表达式节点dictmapping_expr.h / dictmapping_expr.cppDictMappingExpr全局字典优化Global Dictionary Optimization中的字典映射表达式dict_query_expr.h / dict_query_expr.cppDictQueryExpr基于TableReader直接对字典表做 point 查询multi_get的表达式dictionary_get_expr.h / dictionary_get_expr.cppDictionaryGetExpr基于 ComputeEnv 中的 Dictionary Cache 做键值探测probe的表达式dict_functions.h / dict_functions.cppDictFunctionsdict_encode标量函数把常量 VARCHAR 预编码为全局字典码这些表达式统一继承自核心表达式基类Expr见 be/src/exprs/expr.h并重写prepare/open/evaluate_checked/close生命周期方法——这正是它们能无缝接入 BE 向量化执行引擎Chunk批处理执行的前提。三、工厂注册机制三类字典表达式如何被创建与核心内置表达式不同字典表达式属于非核心扩展因此采用注册式挂钩而非直接写死在工厂 switch 中。expr_factory_dict_exprs_extension.cpp 展示了完整机制Status expr_factory_dict_create_post_hook(ObjectPool* pool, const TExprNode texpr_node, Expr** expr, RuntimeState* state) { (void)state; if (*expr ! nullptr) { return Status::OK(); } switch (texpr_node.node_type) { case TExprNodeType::DICT_EXPR: *expr pool-add(new DictMappingExpr(texpr_node)); break; case TExprNodeType::DICT_QUERY_EXPR: *expr pool-add(new DictQueryExpr(texpr_node)); break; case TExprNodeType::DICTIONARY_GET_EXPR: *expr pool-add(new DictionaryGetExpr(texpr_node)); break; default: break; } return Status::OK(); } struct ExprFactoryDictExprsExtensionRegistrar { ExprFactoryDictExprsExtensionRegistrar() { ExprFactory::set_non_core_create_post_hook(expr_factory_dict_create_post_hook); } }; ExprFactoryDictExprsExtensionRegistrar k_expr_factory_dict_exprs_extension_registrar;要点分析通过一个文件级静态对象k_expr_factory_dict_exprs_extension_registrar的构造函数在程序加载期把expr_factory_dict_create_post_hook注册为ExprFactory的non_core_create_post_hook实现零侵入的扩展点接入挂钩函数是post-hook只有当核心工厂尚未创建出表达式*expr nullptr时才按TExprNodeType分发创建这保证了扩展与核心工厂的优先级不冲突三种节点类型对应三种表达式类DICT_EXPR → DictMappingExpr、DICT_QUERY_EXPR → DictQueryExpr、DICTIONARY_GET_EXPR → DictionaryGetExpr这些节点类型定义于 gensrc/thrift/Exprs.thrift 的TExprNodeType枚举中说明 FE 生成的 Thrift 计划节点与 BE 的表达式创建是一一对应的。四、DictMappingExpr全局字典优化中的字典映射4.1 设计背景DictMappingExpr服务于Global Dictionary Optimization全局字典优化。在低基数字符串列的加速场景下StarRocks 会把字符串列编码为全局字典Global Dictionary查询执行直接基于整型字典码进行避免逐行字符串比较。其类注释dictmapping_expr.h阐明了节点结构The original expression will be rewritten as a dictionary mapping function in the global field optimization. child(0) was input lowcardinality dictionary column (input was ID type). child(1) was origin expr (input was string type).即child(0)输入的低基数字典列列内存储的是 ID 整型码child(1)原始字符串表达式。在全局字典优化过程中用字典列作为输入来构造新的字典映射时BE 需要保留原始表达式child(1)以便在执行期把字典码映射回真实值并继续求值。4.2 关键接口与懒重写机制class DictMappingExpr final : public Expr, public DictMappingExprInterface { public: template class Rewrite Status rewrite(Rewrite rewriter) { std::call_once(*_rewrite_once_flag, []() { DCHECK(dict_func_expr nullptr); auto rewrite_result rewriter(); _rewrite_status rewrite_result.status(); if (_rewrite_status.ok()) { dict_func_expr rewrite_result.value(); DCHECK(dict_func_expr ! nullptr); } }); return _rewrite_status; } SlotId slot_id() const; // 取 child(0) 字典列的 slot id Expr* dict_mapping_origin_expr() const; // 返回 child(1) 原始表达式 void set_output_id(SlotId id); // 设置输出 slot void disable_open_rewrite(); // 禁用 open 阶段的自动重写 ... };实现要点同时继承Expr与接口类DictMappingExprInterface定义于 be/src/exprs/dictmapping_expr_interface.h后者提供了dict_mapping_slot_id()、dict_mapping_origin_expr()、rewrite_dict_mapping_expr()、set_dict_mapping_output_id()、disable_dict_mapping_open_rewrite()等抽象方法使上层代码可以面向接口统一处理所有字典映射表达式重写是幂等的、线程安全的用std::call_oncestd::once_flag保证rewrite只真正执行一次多次调用只会返回第一次的结果状态_rewrite_statusdict_func_expr是重写产出的真正的字典函数表达式其输入列是字典码列slot_id()通过down_castconst ColumnRef*(get_child(0))直接取子节点的 slot表明 child(0) 必须是ColumnRef类型。五、DictQueryExpr直连字典表的点查表达式5.1 语义与 Thrift 参数DictQueryExpr的语义是以若干 key 字段为条件对一张字典表执行 point querymulti_get取回 value 字段。其执行参数封装在TDictQueryExprgensrc/thrift/Exprs.thriftstruct TDictQueryExpr { 1: required string db_name // 字典表所在数据库 2: required string tbl_name // 字典表名 3: required mapi64, i64 partition_version // 分区版本 4: required liststring key_fields // 参与查询的 key 字段列表 5: required string value_field // 要取回的 value 字段仅单列 6: required bool strict_mode // 严格模式记录不存在时报错 }5.2 执行期元数据获取open()opendict_query_expr.cpp负责初始化表读取器关键流程通过 RPC 向 FE 拉取表元数据构造TGetDictQueryParamRequest含db_name、tbl_name调用ThriftRpcHelper::rpcFrontendServiceClient的getDictQueryParam得到包含 schema、分区参数partition、节点信息location/nodes_info的响应RPC 超时 30000ms初始化TableReader把 FE 返回的 schema、partition、nodes_info 以及_dict_query_expr.partition_version组装进TableReaderParams创建并init一个TableReader实例TableReader定义于 be/src/storage/table_reader.h这正是 ExprDict 模块依赖Storage的体现构建 key/value schema基于OlapTableSchemaParam解析出的列定义用StorageSchemaHelper::convert_field把与key_fields匹配的列构造成_key_schema每列一个 field把value_field匹配的列构造成_value_schema建立 slot id 映射遍历响应中的slot_descs为 key 列填充_key_slot_ids、为 value 列填充_value_slot_id。5.3 批处理求值evaluate_checked()evaluate_checkeddict_query_expr.cpp是向量化执行的核心流程如下求值子表达式依次对children()求值得到各输入列child(0) 之外是 key 列常数列用ColumnHelper::unpack_and_duplicate_const_column展开为size行组装 key Chunkkey 列取自columns[1] ~ columns[1 key_fields.size()]组装成带_key_schema的Chunk并注册 slot id 到列索引的映射随后做空值校验key 列不允许为 NULL否则返回Status::InternalError(invalid parameter : get NULL paramenter)nullable 列会被转换为非 nullable执行 multi_get调用_table_reader-multi_get(*key_chunk, {value_field}, found, *value_chunk)found数组标记每个 key 是否命中组装结果以value_chunk列克隆出可空的结果列逐行遍历命中则append_datum真实值未命中时若strict_mode为 truenull_if_not_found false则返回Status::NotFound否则append_nulls(1)补 NULL。可以看到DictQueryExpr的字典查询走的是直连存储引擎的点查路径TableReader::multi_get适合数据量较小的字典表按 key 精确取值。六、DictionaryGetExpr基于 Dictionary Cache 的探测表达式6.1 语义与 Thrift 参数DictionaryGetExpr服务于ComputeEnv 中的字典缓存Dictionary Cache把 key 列组装成 chunk在内存字典缓存中做批量探测probe返回值字段聚合为一个 STRUCT 列。其参数封装在TDictionaryGetExprgensrc/thrift/Exprs.thriftstruct TDictionaryGetExpr { 1: optional i64 dict_id // 字典缓存 ID 2: optional i64 txn_id // 事务版本号用于定位具体版本的字典 3: optional i32 key_size // key 字段个数 4: optional bool null_if_not_exist // 未命中时是否置 NULL否则走严格报错路径 }6.2 prepare绑定字典缓存与 schemapreparedictionary_get_expr.cpp做静态初始化获取缓存管理器经由state-exec_env()-compute_env()-dictionary_cache_manager()拿到DictionaryCacheManagerbe/src/compute_env/dictionary_cache/dictionary_cache_manager.h任一环节缺失即返回Status::InternalError(...missing compute dictionary cache manager)体现 ExprDict 对ComputeEnv的依赖按 id 取 schemaget_dictionary_schema_by_id(dict_id)拿不到则报错 there is no cache for dictionary: {dict_id}按版本取字典get_dictionary_by_version(dict_id, txn_id)拿到_dictionaryDictionaryCachePtr保证读到的是txn_id对应的事务版本数据预建 Chunk 模板用 schema 的前key_size个字段构造_key_chunk、其余字段构造_value_chunk再基于 value 列模板构造一个nullable StructColumn_nullable_struct_column——每个 value 子列先包一层 nullable再作为 STRUCT 的 field用于承载某些行未命中的情况。6.3 evaluate_checked缓存探测并输出 STRUCTevaluate_checkeddictionary_get_expr.cpp求值 key 子表达式children()的第 0 项起是构造 key 的表达式任一输入列含 NULL 即返回Status::InternalError(...get NULL paramenter)常数列展开、nullable 列剥壳批量探测调用DictionaryCacheManager::probe_given_dictionary_cache(key_schema, value_schema, _dictionary, key_chunk, value_chunk, null_column)其中null_column仅在null_if_not_exist为 true 时传入用于标记未命中行合并为 STRUCT把value_chunk的每一列 append 到_nullable_struct_column对应 field 列中并用 SIMD 指令SIMD::contain_nonzero见 be/src/base/simd/simd.h扫描 null 标记列设置 STRUCT 列的全局 null 标记最后返回整个 nullable StructColumn。与DictQueryExpr的落盘点查不同DictionaryGetExpr走的是内存缓存探测路径返回值天然支持多列聚合为 STRUCT更适合高频、低延迟的字典关联场景。七、dict_encode常量值预编码标量函数除了三类表达式节点exprs_ext/dict还提供DictFunctions静态类其dict_encode是一个支持向量化的标量函数DEFINE_VECTORIZED_FN。函数签名与语义dict_functions.hdict_encode(value, dict_slot_id)把常量 VARCHAR翻译为指定全局字典列dict_slot_id标识的字典码供低基数重写后的array_contains(dict_array, dict_encode(foo, slot))这类比较直接在整型码上进行值不在字典中时编码为std::numeric_limitsDictId::max()哨兵值保证必定缺席等值/成员判断语义正确但不能用于大小比较NULL 输入编码为 NULL。dict_encode_preparedict_functions.cpp在FRAGMENT_LOCAL作用域初始化函数状态校验dict_slot_id必须是非空常量否则Status::InternalError校验value必须是常量若为 NULL 常量则直接记录is_null true通过runtime_state-fragment_dict_state()拿到FragmentDictStatebe/src/compute_env/global_dict/fragment_dict_state.h调用其mutable_dict_optimize_parser()-lookup_dict_code(runtime_state, slot_id, value)完成执行期常量查码。求值时dict_functions.cpp只需根据EncodeDictState返回常量列NULL 输入返回create_const_null_column否则返回TYPE_INT常量列code。该实现把昂贵的字符串查字典操作收敛在prepare阶段执行一次运行时零字符串处理是典型的以预计算换执行速度的设计。八、模块边界的工程意义与扩展指南8.1 依赖方向与可维护性从 AGENTS.md 与 manifest 可以提炼出 ExprDict 的依赖铁律ExprDict字典语义、工厂注册 ├── Expr表达式生命周期契约prepare/open/evaluate/close ├── ComputeEnvFragmentDictState、DictionaryCacheManager └── Storage / StoragePrimitiveTableReader、StorageSchemaHelper └── 更底层column/ types/ base/ gutil/ platform/ gen_cpp/同时禁止向上依赖service/、http/、agent/、connector/。这样做的收益是字典表达式可以被独立编译ExprDict目标与单测不拖带整个 BE 服务层共享的表达式抽象如DictMappingExprInterface沉淀在Expr模块扩展与核心解耦变更影响面可控FE 只要把DICT_EXPR / DICT_QUERY_EXPR / DICTIONARY_GET_EXPR三类节点下发到 BEBE 侧的注册挂钩会自动完成实例化无需改动核心ExprFactory。8.2 如何新增一个字典表达式遵循本模块的既有模式新增字典表达式的推荐步骤是在be/src/exprs_ext/dict/下新建xxx_expr.h/.cpp继承Expr实现prepare/open/evaluate_checked/close在 gensrc/thrift/Exprs.thrift 中补充节点类型与参数 struct如TDictQueryExpr模式FE 侧同步下发在 expr_factory_dict_exprs_extension.cpp 的switch中增加一个case分支完成创建保持 include 与 target 依赖不越界对照 manifest 的 allow 列表并可用仓库自带的边界校验脚本机械验证。8.3 边界校验的工程化落地AGENTS.md 明确指出本节内容由 be/module_boundary_manifest.json 自动生成并给出了两条配套命令# 修改 manifest 后重新生成各模块 AGENTS.md python3 build-support/render_be_agents.py --write # 机械地校验模块边界规则是否被满足 python3 build-support/check_be_module_boundaries.py --mode full其中check_be_module_boundaries.py与render_be_agents.py均位于 build-support/ 目录。这套机制保证了文档声明 → 代码约束 → CI 校验三者一致开发者阅读的 AGENTS.md 永远与 manifest 中的规则同步任何越过边界的 include 或 target 依赖都会在构建前被脚本拦截。对于希望为 StarRocks 贡献字典类表达式例如新的字典编码函数、新的字典查询策略的开发者这既是开发指南也是提交前必须通过的自动检查。九、小结StarRocks 的 ExprDict 模块以一份 AGENTS.md 为核心契约通过 module_boundary_manifest.json 精确划定了字典表达式扩展这一层级的职责与依赖DictMappingExpr承载全局字典优化中的表达式重写dictmapping_expr.hDictQueryExpr通过TableReader直连字典表执行 multi_get 点查dict_query_expr.cppDictionaryGetExpr依托DictionaryCacheManager做内存缓存批量探测并输出 STRUCTdictionary_get_expr.cppdict_encode则在prepare期完成常量预编码dict_functions.cpp最后由 expr_factory_dict_exprs_extension.cpp 的 post-hook 统一接入ExprFactory。理解这一模块的边界与实现是深入 StarRocks 全局字典优化与字典缓存执行链路的最佳切入点。【免费下载链接】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),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

DanaBot银行木马深度剖析:架构、攻击链与防御实战 2026/9/15 20:02:33

DanaBot银行木马深度剖析:架构、攻击链与防御实战

前阵子在处理一批恶意邮件样本时,又看到DanaBot活跃的身影。这玩意儿第一次出现在大众视野是2018年,当时主要盯上大洋洲的银行客户,后来一路扩散到欧洲多国和拉美地区,到现在还在不断变种。作为一类典型的银行木马病毒&#xff0c…

阅读更多 →
Nixpkgs 的 teTeX / TeX Live 环境钩子:texmf-nix 树与 TEXINPUTS 注入机制解析 2026/9/15 20:02:33

Nixpkgs 的 teTeX / TeX Live 环境钩子:texmf-nix 树与 TEXINPUTS 注入机制解析

Nixpkgs 的 teTeX / TeX Live 环境钩子:texmf-nix 树与 TEXINPUTS 注入机制解析 【免费下载链接】nixpkgs Nix Packages collection & NixOS 项目地址: https://gitcode.com/GitHub_Trending/ni/nixpkgs 导读:本文围绕 Nixpkgs 中 tetex-tex-l…

阅读更多 →
使用 lm-evaluation-harness 评估西班牙语社会偏见:EsBBQ 任务组完整指南 2026/9/15 20:02:33

使用 lm-evaluation-harness 评估西班牙语社会偏见:EsBBQ 任务组完整指南

使用 lm-evaluation-harness 评估西班牙语社会偏见:EsBBQ 任务组完整指南 【免费下载链接】lm-evaluation-harness A framework for few-shot evaluation of language models. 项目地址: https://gitcode.com/GitHub_Trending/lm/lm-evaluation-harness 导读…

阅读更多 →
AI Agent工程化落地:架构设计与性能优化实战 2026/9/15 20:02:33

AI Agent工程化落地:架构设计与性能优化实战

1. AI Agent工程化落地指南及技术详解AI Agent作为人工智能领域的重要分支,正在从实验室走向产业应用。不同于传统AI模型,AI Agent具备自主感知、决策和执行能力,能够独立完成复杂任务。但要将AI Agent真正落地到生产环境,需要解决…

阅读更多 →
jemalloc 内存监控实战:从 mallctl 到生产告警的 5 步路径 2026/9/15 20:02:33

jemalloc 内存监控实战:从 mallctl 到生产告警的 5 步路径

jemalloc 内存监控实战:从 mallctl 到生产告警的 5 步路径 【免费下载链接】jemalloc 项目地址: https://gitcode.com/GitHub_Trending/je/jemalloc 从一条凌晨告警说起 凌晨三点,告警群被"RSS 持续上涨"刷屏。服务链着 jemalloc&…

阅读更多 →
VeraCrypt 磁盘加密实战:3 步建出你的第一块加密硬盘 2026/9/15 19:59:33

VeraCrypt 磁盘加密实战:3 步建出你的第一块加密硬盘

VeraCrypt 磁盘加密实战:3 步建出你的第一块加密硬盘 【免费下载链接】VeraCrypt Disk encryption with strong security based on TrueCrypt 项目地址: https://gitcode.com/GitHub_Trending/ve/VeraCrypt U 盘落在出租车上,里面的资料却再也找不…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞