- 数据库
- OLAP
- 数据仓库
- 大数据
- 湖仓一体
- 数据分析
【免费下载链接】starrocks
The 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.
encode_sort_key是 StarRocks 提供的一个工具函数,它能把多列异构数据(整数、浮点数、字符串、日期时间等)编码为一个保序(order-preserving)的 VARBINARY 复合排序键,使排序键的字典序比较结果与原始数据的排列顺序完全一致。本文将以官方 SQL 函数文档为主线,结合 StarRocks 仓库中 FE 注册逻辑、BE 向量化实现与单元测试,系统讲解该函数的语法、类型支持、编码策略、NULL 处理、典型用法(生成列与 JSON 字段提取)及工程化使用建议,帮助你在建表与查询优化中正确运用这一能力。
函数定位:它解决什么问题
在 StarRocks 的表中,排序键(sort key) 决定了数据在存储引擎内的物理排列顺序,直接影响范围查询与前缀查询的效率。传统建表时,ORDER BY只能直接引用原始列;当希望按多列拼接后的复合键排序,或排序依据来自计算表达式(如 JSON 字段提取结果)时,就需要一个能把异构类型统一编码为可比较二进制串的函数——这就是encode_sort_key的定位。
从 FE 源码可见,该函数与其他编码类函数(如encode_fingerprint_sha256)一起在 FunctionSet.java 中注册,其 BE 端向量化实现在 utility_functions.h 中通过DEFINE_VECTORIZED_FN(encode_sort_key)声明,属于exprs_ext(扩展表达式)模块。
语法与参数
encode_sort_key(column1, column2, ..., columnN)column1, column2, ..., columnN:一个或多个任意受支持数据类型的列或表达式,函数接受可变数量参数。实际使用中建议至少传入一列,且列数不宜过多(详见下文"键长度限制")。- 返回值:
VARBINARY类型,即编码后的复合排序键。二进制键的字典序(lexicographic)比较结果与原列组合的排序结果一致。
支持的数据类型
| 数据类型 | 说明 |
|---|---|
TINYINT | 8 位有符号整数 |
SMALLINT | 16 位有符号整数 |
INT | 32 位有符号整数 |
BIGINT | 64 位有符号整数 |
LARGEINT | 128 位有符号整数 |
FLOAT | 32 位浮点数 |
DOUBLE | 64 位浮点数 |
VARCHAR | 变长字符串 |
CHAR | 定长字符串 |
DATE | 日期值 |
DATETIME | 日期时间值 |
TIMESTAMP | 时间戳值 |
以下复杂类型不支持,直接传入将返回错误:
JSONARRAYMAPSTRUCTHLLBITMAPPERCENTILE
对于 JSON 等复杂类型,文档明确给出了替代方案:先通过 JSON 提取函数取到原始值,再作为参数传入(见下文"JSON 字段提取"与"类型限制"小节)。
编码策略:字典序如何保持
为了让生成的二进制键在字典序比较下等价于原始数据的排序顺序,encode_sort_key对不同类型采用了不同的编码策略:
- 整数类型:采用大端字节序(big-endian),并翻转符号位(signed 类型)。大端序保证数值高位在前,使字节序比较与数值大小一致;符号位翻转使负数在字典序上排在正数之前(例如
-1编码后字典序小于1)。 - 浮点类型:使用自定义编码,确保浮点数的大小关系在二进制比较中保持正确(对 IEEE-754 位模式做符号相关的变换)。
- 字符串类型:采用**
0x00字节转义**的特殊编码,非末尾字段以0x00 0x00作为终止符。这样既能区分字符串内部可能出现的0x00字节,又能保证前缀不相同的字符串按字典序正确排列。 - 日期/时间类型:将内部整数表示(如自纪元起的刻度)按整数值编码,使时间先后顺序与键的字典序一致。
NULL 处理
- 每一行、每一列都会写入一个NULL 标记字节:
0x00表示该列为 NULL,0x01表示非 NULL。 - 即使是非空列(NOT NULL)也会追加标记,以保证编码结构统一、长度可预期。
- 列与列之间使用分隔字节
0x00(最后一列之后不再追加)。
这套规则保证了 NULL 与非 NULL、不同长度字符串混排时,键的比较结果依然稳定、无歧义。
使用示例
生成排序键列(Generated Column)
最常见的用法是将encode_sort_key放在生成列定义中,配合ORDER BY将复合排序键作为表的主排序键:
CREATE TABLE user_analytics ( user_id INT, region VARCHAR(50), score DOUBLE, created_date DATE, sort_key VARBINARY(1024) AS ( encode_sort_key(region, score, created_date) ) ) ORDER BY (sort_key);此表按region、score、created_date三列的复合顺序物理排序:先按区域字符串,再按分数,最后按日期。生成列由系统在写入时自动计算,查询时可对sort_key直接做范围扫描,天然支持对前三列组合的前缀条件查询。
JSON 字段提取
当排序依据来自 JSON 内的字段时,先用 JSON 提取函数取出原始值再编码:
CREATE TABLE json_data ( id INT, json_content JSON, sort_key VARBINARY(1024) AS ( encode_sort_key( get_json_int(json_content, '$.priority'), get_json_string(json_content, '$.category'), get_json_double(json_content, '$.score') ) ) ) ORDER BY (sort_key);这等价于对json_content中的priority、category、score三个字段做复合排序,同时规避了 JSON 类型本身无法直接编码的限制。
限制与注意事项
类型限制
复杂类型(JSON、ARRAY、MAP、STRUCT、HLL、BITMAP、PERCENTILE)不能直接编码,需要先用提取/转换函数拿到原始值:
-- 不要这样写:encode_sort_key(json_col) -- 应当这样写:encode_sort_key(get_json_int(json_col, '$.field1'), get_json_string(json_col, '$.field2'))性能考虑
- 每次调用
encode_sort_key都需要对所有输入列完成编码,属于有一定开销的计算; - 编码后的二进制键可能显著大于原始数据(NULL 标记、分隔符、转义字节都会增加体积),从而增加存储与比较成本;
- 官方文档明确建议:使用生成列(generated column)避免重复编码——写入时计算一次,查询期直接复用。
键长度限制
- 建议控制列数(通常不超过 10 列),列越多键越长、比较开销越大;
- 尽量选择较短的字符串列参与编码;
- 对超长字符串,可考虑先用哈希函数(如
encode_fingerprint_sha256,同样注册于 FunctionSet.java)压缩后再参与编码,换取存储与比较效率(代价是可能引入哈希碰撞,需结合业务评估)。
源码与测试佐证
- FE 函数注册:
encode_sort_key在 FunctionSet.java 中定义为ENCODE_SORT_KEY常量,并与其他 utility 函数一并注册到内置函数集,供 SQL 解析与优化器调用。 - BE 向量化实现入口:BE 端在 utility_functions.h 中声明
DEFINE_VECTORIZED_FN(encode_sort_key),实现位于exprs_ext/utility模块,按向量化批量方式逐行完成多列编码。 - 单元测试:utility_functions_test.cpp 覆盖了单列、多列、常量列(const)与普通列混合等多种调用形态,验证编码结果与排序语义的正确性。
- 存储侧支持:排序键的列索引与唯一标识在 Descriptors.thrift(
sort_key_uid)与 AgentService.thrift(sort_key_idxes/sort_key_unique_ids)中有对应定义,说明生成排序键最终会下推到 BE 存储层参与实际数据排布。
小结
encode_sort_key是 StarRocks 中为数不多的、面向排序键构造的编码类工具函数:它把异构类型的多列数据编码为保序的 VARBINARY 复合键,配合生成列与ORDER BY即可在写入时固化复合排序顺序,从而提升范围查询与前缀查询效率。使用时需牢记三点:复杂类型必须先提取为原始值;优先用生成列避免重复计算;控制列数与字符串长度,必要时借助哈希函数折衷。
- 数据库
- OLAP
- 数据仓库
- 大数据
- 湖仓一体
- 数据分析
【免费下载链接】starrocks
The 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.
相关推荐
StarRocks bitmap_to_binary 函数详解:BITMAP 数据的二进制序列化与导出实战
StarRocks bitmap_to_binary 函数详解:BITMAP 数据的二进制序列化与导出实战 bitmap_to_binary 是 StarRoc
数据库OLAP数据仓库大数据湖仓一体数据分析StarRocks array_agg 聚合函数完全指南:多行聚合为数组与 ORDER BY 排序实战
StarRocks array_agg 聚合函数完全指南:多行聚合为数组与 ORDER BY 排序实战 array_agg 是 StarRocks 中用于将一列
数据库OLAP数据仓库大数据湖仓一体数据分析StarRocks array_generate 函数详解:序列生成与逐行数组构造实战
StarRocks array_generate 函数详解:序列生成与逐行数组构造实战 导读 array_generate 是 StarRocks 从 v3.1
数据库OLAP数据仓库大数据湖仓一体数据分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考