ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

StarRocks materialize 函数:FE 优化器的“优化屏障“用法与源码实现解析

StarRocks materialize 函数:FE 优化器的“优化屏障“用法与源码实现解析 数据库OLAP数据仓库大数据湖仓一体数据分析【免费下载链接】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点击查看免费下载materialize()是 StarRocks 提供的一个特殊工具函数它原样返回输入表达式的值但在 FrontendFE查询优化器眼中却是不透明的能够阻断常量折叠、分区裁剪等改写规则对被包裹表达式的优化。它主要用于查询执行的测试与调试场景。本文以 SQL 函数文档 为核心结合 FE 优化器、BE 向量化执行与函数注册表等仓库源码完整讲解其语法、参数类型、行为语义、实战用法与底层实现原理。为什么需要优化屏障从分区裁剪说起StarRocks 的查询优化器CBO在生成物理执行计划前会对逻辑计划做大量等价改写以提升执行效率。其中最常见的一类优化是基于谓词的裁剪常量折叠Constant Folding把1 2这类可在编译期算完的表达式直接替换为常量3减少运行时计算分区裁剪Partition Pruning当 WHERE 条件命中分区列且条件可被求值时优化器会直接跳过不满足条件的分区只扫描必要分区对应 FE 的PartitionPruneRule见 PartitionPruneRule.java从物理上大幅减少扫描数据量此外还有列裁剪、谓词下推、表达式改写等各类 Transformation Rule。这些优化绝大部分情况下是有益的但它们也让查询究竟怎么执行、扫描了哪些数据变得不那么直观。在以下场景中开发者反而希望关闭这些优化验证查询结果不依赖分区裁剪是否生效例如测试某个过滤条件下游算子是否正确处理全量输入调试某条查询的执行计划观察未经改写时算子的真实行为构造测试用例确保某个表达式在运行时被真实计算而非被常量替换。materialize()正是为此而生的优化屏障optimization barrier。把任意表达式用materialize()包起来后FE 优化器就无法对它应用常量折叠、分区裁剪及其他改写但函数的计算结果与原表达式完全一致——即输入什么就返回什么。语法与参数materialize()的语法极为简单只有一个参数materialize(x);参数说明x需要原样穿透的表达式。支持的数据类型BOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、VARCHAR、DATE、DATETIME、DECIMALV2、DECIMAL32、DECIMAL64、DECIMAL128、DECIMAL256、JSON、VARBINARY。上述 18 种类型一一对应了 FE 内置函数表中的注册项。在 functions.py 中可以清晰看到materialize的 18 个重载声明每个重载的函数 ID 从100030到100047参数类型与返回类型完全相同且统一映射到 BE 端的UtilityFunctions::materialize实现# materialize: identity function that acts as an optimization barrier. [100030, materialize, True, False, BOOLEAN, [BOOLEAN], UtilityFunctions::materialize], [100031, materialize, True, False, TINYINT, [TINYINT], UtilityFunctions::materialize], ... [100047, materialize, True, False, VARBINARY, [VARBINARY], UtilityFunctions::materialize],这一注册表同时定义了函数名常量FunctionSet.MATERIALIZE materialize见 FunctionSet.java。返回值返回与输入完全相同的值和类型。从实现角度看这是一个恒等函数FE 侧materialize被列入一元函数集合DECIMAL_UNARY_FUNCTION_SET见 DecimalV3FunctionAnalyzer.java类型分析时保持输入类型不变、不做隐式提升BE 侧向量化实现只做一件事——返回输入列本身见 utility_functions.cppStatusOrColumnPtr UtilityFunctions::materialize(FunctionContext* context, const Columns columns) { return Column::mutate(columns[0]); }也就是说materialize()在计算层面是纯透传的运行时开销近乎为零。它的价值全部体现在 FE 优化器对它的一视同仁——它被当作一个普通函数调用无法被折叠或裁剪掉。函数头的注释也明确说明了这一点见 utility_functions.hIdentity function that acts as an optimization barrier. Returns the input value unchanged but prevents FE optimizations such as constant folding and partition pruning.示例如何阻止分区裁剪假设sales表按日期列dt做了分区常规写法下优化器会对dt做分区裁剪-- Without materialize: partition pruning applies SELECT * FROM sales WHERE dt 2024-01-01;执行上述查询时FE 的PartitionPruneRule会分析dt 2024-01-01这个谓词只保留 2024-01-01 之后的分区参与扫描。而把dt用materialize()包裹后谓词变成了materialize(dt) 2024-01-01。此时分区列上是一个函数调用表达式而非裸列引用优化器无法从中推导出确定的分区范围分区裁剪被禁用所有分区都会被扫描-- With materialize: partition pruning is disabled on dt SELECT * FROM sales WHERE materialize(dt) 2024-01-01;两种写法的结果完全一致区别只在于扫描路径不同。这正是文档示例所演示的用法用它来验证不依赖分区裁剪时查询结果是否正确。示例如何阻止常量折叠常量折叠会被materialize()阻断但计算结果不受影响SELECT materialize(1 2); ------------------- | materialize(1 2)| ------------------- | 3 | -------------------从结果看1 2依然算出3区别在于这个3是在运行时由materialize的输入表达式求值得到的而不是优化器在生成计划前把1 2直接替换成字面量3。因此materialize适合用来验证某个表达式在不做常量折叠的前提下计算结果是否仍然正确。更丰富的实战用例来自仓库测试用例仓库中提供了针对materialize()的完整回归测试用例 test_materialize覆盖了比文档更全面的行为边界可以直接作为实战参考1各种标量类型逐一透传包括 NULL 输入select materialize(true); -- 1 select materialize(cast(1.5 as float)); -- 1.5 select materialize(parse_json({a: 1})); -- {a: 1} select materialize(cast(binary as varbinary)); -- binary select materialize(cast(null as int)); -- NoneNULL 原样穿透2任意表达式结果被保留select materialize(concat(hello, , world)); -- hello world select materialize(cast(2024-06-15 as date) cast(2024-01-01 as date)); -- 13嵌套调用合法select materialize(materialize(42)); -- 424作用在表列上的谓词 / 投影 / 聚合select * from t1 where materialize(c1) 1 order by c1; select * from t1 where materialize(c3) 2024-06-01 order by c1; select sum(materialize(c1)), count(materialize(c2)) from t1;这些用例说明materialize()可以安全地出现在 WHERE 谓词、SELECT 投影和聚合参数中返回结果与不使用它时完全一致可以作为优化无关性的验证手段。深层原理函数如何注册、识别与执行把materialize的完整链路串起来可以看到它横跨 FE 与 BE 两个进程FE 注册functions.py生成内置函数元数据FunctionSet中定义MATERIALIZE常量并将其登记为内建函数FunctionSet.java。FE 类型分析DecimalV3FunctionAnalyzer将materialize归入一元函数集合DecimalV3FunctionAnalyzer.java返回类型与输入类型严格一致。FE 优化由于被包裹的子表达式藏在一个普通函数调用内部优化器规则无法对其内部进行常量折叠、分区裁剪等改写——这就是屏障的由来。相比之下未被包裹的分区谓词会由PartitionPruneRulePartitionPruneRule.java结合OptOlapPartitionPruner做剪枝。BE 执行DEFINE_VECTORIZED_FN(materialize)utility_functions.h声明向量化实现UtilityFunctions::materialize直接返回输入列utility_functions.cpp保证运行时语义是纯粹的恒等映射。使用注意事项materialize()是测试与调试工具不是性能优化手段。正常情况下请勿在生产查询中滥用——它刻意禁用分区裁剪和常量折叠会使查询扫描更多分区、执行更多运行时计算通常会导致性能下降。它不改变查询语义与结果只改变优化器如何处理被包裹表达式这一行为。若你只是希望查看执行计划差异可以配合EXPLAIN观察是否出现分区裁剪再与materialize()包裹后的计划进行对比从而定位优化器行为。小结materialize()是 StarRocks 中一个简单到极致、作用却非常精准的工具函数语法上只有一个参数语义上完全恒等但在 FE 优化器面前是可靠的优化屏障。借助它开发者可以在测试与调试中精确控制常量折叠、分区裁剪等优化是否作用于某个表达式从而验证查询在不依赖特定优化时的正确性。它的实现横跨函数注册functions.py、类型分析DecimalV3FunctionAnalyzer.java与 BE 向量化执行utility_functions.cpp是理解 StarRocks 优化器行为边界的一个绝佳切入点。更多行为细节可查阅官方文档 materialize 与仓库回归测试 test_materialize。赞分享数据库OLAP数据仓库大数据湖仓一体数据分析【免费下载链接】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 min_by 聚合函数详解从语法语义到 FE 源码实现StarRocks min_by 聚合函数详解从语法语义到 FE 源码实现 本篇基于 StarRocks 官方函数文档系统讲解 min_by 聚合函数的语法数据库OLAP数据仓库大数据湖仓一体数据分析StarRocks days_sub 日期函数详解SQL 用法、边界行为与 BE/FE 双层源码实现StarRocks days_sub 日期函数详解SQL 用法、边界行为与 BE/FE 双层源码实现 days_sub 是 StarRocks 中用于日期/时数据库OLAP数据仓库大数据湖仓一体数据分析StarRocks any_value 聚合函数语法实战、复杂类型支持与 BE/FE 源码实现解析StarRocks any_value 聚合函数语法实战、复杂类型支持与 BE/FE 源码实现解析 any_value 是 StarRocks 提供的一个轻量数据库OLAP数据仓库大数据湖仓一体数据分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表