StarRocks reverse 函数详解:字符串与数组反转的语法、限制与实现原理
【免费下载链接】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
本篇技术指南围绕 StarRocks 内置函数reverse()展开,该函数用于将字符串字符或一维数组元素按相反顺序重新排列,是 ETL 清洗、日志处理、序列反转等 SQL 场景中常用的内置函数。读完本文,你将掌握reverse()的完整语法、参数类型约束、返回值规则与可运行的 SQL 示例,并通过 BE(Backend)与 FE(Frontend)源码理解其在 StarRocks 内部的向量化执行机制。
函数概览
reverse是 StarRocks 内置的标量函数(scalar function),可作用于字符串与数组两类数据:
- 对字符串:将字符串中的字符按逆序输出,例如
reverse('hello')返回olleh; - 对数组:将数组中的元素按逆序排列,例如
reverse([4,1,5,8])返回[8,5,1,4]。
该函数由 FE 端在 FunctionSet.java 中以REVERSE = "reverse"注册为内建函数,并由 BE 端向量化执行引擎实现,属于开箱即用的系统函数,无需额外配置或创建。
语法
reverse(param)参数说明
param:待反转的字符串或数组,支持以下数据类型:
| 类别 | 支持的类型 |
|---|---|
| 字符串 | VARCHAR、CHAR |
| 数组 | ARRAY |
当param为数组时,当前版本只支持一维数组,且数组元素不能为 DECIMAL 类型。支持的元素类型如下:
BOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、VARCHAR、DECIMALV2、DATETIME、DATE、JSON
说明:JSON 类型元素自 StarRocks 2.5 版本起开始支持。
返回值
返回类型与param的类型保持一致,即反转字符串仍返回字符串,反转数组仍返回同类型数组,不会发生类型转换。
使用示例
示例 1:反转字符串
MySQL > SELECT REVERSE('hello'); +------------------+ | REVERSE('hello') | +------------------+ | olleh | +------------------+ 1 row in set (0.00 sec)示例 2:反转一维数组
MYSQL> SELECT REVERSE([4,1,5,8]); +--------------------+ | REVERSE([4,1,5,8)] | +--------------------+ | [8,5,1,4] | +--------------------+示例 3:在表查询中应用
将reverse()与列引用结合使用,可以完成字段级的字符或元素反转:
-- 反转字符串列 SELECT reverse(name) FROM user_profile; -- 反转数组列 SELECT reverse(tags) FROM article WHERE id = 1001; -- 与字符串函数组合使用 SELECT reverse(lower('StarRocks'));当传入的字符串或数组为NULL时,函数返回NULL。
源码级实现原理
reverse()在 FE 与 BE 两个层面协同工作,理解其实现有助于评估性能特征与适用范围。
字符串反转:区分 ASCII 与 UTF-8 两条路径
字符串反转的入口位于 BE 端 string_functions.cpp:
StatusOr<ColumnPtr> StringFunctions::reverse(FunctionContext* context, const Columns& columns) { return VectorizedUnaryFunction<ReverseFunction>::evaluate<TYPE_VARCHAR>(columns[0]); }其核心是ReverseFunction模板(string_functions.cpp),实现上会对输入字符串做一次快速 ASCII 判定(validate_ascii_fast):
- 若整串为 ASCII,走
reverse<true>路径,使用ascii_reverse_per_slice按字节直接反转,性能最优; - 若包含非 ASCII 字符(如中文等多字节 UTF-8 字符),走
reverse<false>路径,使用utf8_reverse_per_slice按 UTF-8 字符边界反转,保证多字节字符不会被截断或乱码。
因此,reverse()对中文等多字节字符同样安全,只是会切换至 UTF-8 感知路径,处理开销略高。
数组反转:按列类型分派
数组反转由ArrayReverse模板类实现,位于 array_functions.tpp,入口process()首先处理空列与常量列(only_null/unpack_and_duplicate_const_column),随后根据数组元素类型分派到不同的底层反转例程:
_reverse_fixed_column:针对 BOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、DATETIME、DATE 等定长类型,基于数组偏移量对元素块调用std::reverse;_reverse_binary_column:针对 VARCHAR 等变长类型,先反转偏移量再反转字节区,并逐字符串回正,保证每个字符串内部字节序不变;_reverse_json_column:针对 JSON 元素,直接对 JsonColumn 的字符串池做反转;DECIMALV2等其余类型则走_reverse_data_column的通用定长/变长分支。
从该实现可以看出,数组反转是**逐行(按数组)**进行的原地/拷贝反转,反转的是“元素顺序”而非元素本身,因此对于元素为复杂对象(如 JSON)的数组同样成立。
函数注册链路
FE 端在 FunctionSet.java 声明REVERSE = "reverse"并完成内建函数注册,随后由 SQL 优化器将reverse()下推至 BE 的向量化执行算子。在执行期,BE 依据参数类型分别派发到上述字符串或数组实现路径。
使用限制与注意事项
使用reverse()时请留意以下几点:
- 仅支持一维数组:多维嵌套数组不在支持范围内;
- DECIMAL 元素不支持:若数组元素为 DECIMAL 类型,函数将无法处理;若需对数值反转,可先将 DECIMAL 转成 VARCHAR 再调用;
- JSON 元素版本要求:JSON 类型的数组元素需要 StarRocks 2.5 及以上版本;
- NULL 语义:输入为
NULL时返回NULL; - 多字节安全:对字符串执行反转时,StarRocks 会按字符边界处理 UTF-8 编码,无需担心中文等字符被截断。
总结
reverse()是一个轻量但实用的系统函数:字符串场景下自动区分 ASCII 与 UTF-8 两条执行路径保证正确性与性能,数组场景下按元素类型分派到定长、变长或 JSON 专用反转例程。无论是清洗反序存储的日志字符串,还是翻转数组列中的元素顺序,都可以直接使用SELECT reverse(...)完成,无需编写自定义 UDF。更多数组相关函数可参考 array-functions 所在目录下的其他文档。
【免费下载链接】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),仅供参考