StarRocks cardinality() 函数详解:获取数组与 Map 元素个数的权威指南

发布时间:2026/9/17 17:50:42
StarRocks cardinality() 函数详解:获取数组与 Map 元素个数的权威指南 StarRocks cardinality() 函数详解获取数组与 Map 元素个数的权威指南【免费下载链接】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/starrockscardinality()是 StarRocks 中用于返回数组ARRAY元素个数的内置函数也是array_length()的别名两者语义完全等价。本指南围绕该函数展开覆盖语法、参数、NULL 语义、嵌套数组行为、源码级实现原理、函数注册机制与单元测试验证并给出可直接复制的 SQL 示例帮助你准确使用它在多维分析、实时分析和即席查询场景中计算数组维度信息。函数概述返回数组元素个数cardinality()接收一个数组作为输入返回该数组的元素个数结果类型为INT。它是array_length()的别名从 StarRocks v3.0 起开始支持。核心语义要点统计元素个数返回数组中元素的个数而不是数组在存储上的字节大小NULL 输入返回 NULL如果输入参数本身为 NULL结果同样为 NULLNULL 元素计入长度数组内部的 NULL 元素会计入长度不会被跳过结果为 INT返回值类型为INT无论数组元素是什么类型。该函数在 StarRocks 官方文档中的定义见 cardinality.md其别名文档为 array_length.md。语法与参数cardinality()的函数签名如下INT cardinality(any_array)参数说明any_array需要获取元素个数的 ARRAY 值可以是任意元素类型的数组也支持嵌套数组多维数组参数说明any_array可以是字面量数组、数组类型的列也可以是返回数组类型的表达式支持任意元素类型INT、VARCHAR、DECIMAL 等以及嵌套的 ARRAYARRAY... 多维数组数组参数还可以来自array_agg()等聚合函数构造的结果或来自unnest表函数展开后的中间结果。返回值与 NULL 语义cardinality()的返回值类型为INT其 NULL 语义遵循以下规则输入情况返回值说明普通数组[1,2,3]3返回元素个数含 NULL 元素的数组[1,2,3,null]4NULL 元素会计入长度空数组[]0空数组长度为 0NULL 输入NULL输入为 NULL 时结果也是 NULL值得注意的区别是数组元素为 NULL 与整个数组为 NULL 是两种不同的情况。[NULL]是一个包含一个 NULL 元素的数组其长度为 1而数组本身为 NULL即该数组列取值为 NULL时cardinality()返回 NULL。这一点可以从仓库中的单元测试得到印证详见下文测试验证一节。使用示例以下示例均可在 StarRocks 的 MySQL 客户端中直接执行。一维数组统计元素个数mysql select cardinality([1,2,3]); ----------------------- | cardinality([1,2,3]) | ----------------------- | 3 | ----------------------- 1 row in set (0.00 sec)NULL 元素计入长度mysql select cardinality([1,2,3,null]); ------------------------------ | cardinality([1, 2, 3, NULL]) | ------------------------------ | 4 | ------------------------------可以看到数组中的 NULL 元素被计入总数结果为 4。嵌套数组只统计第一层元素个数mysql select cardinality([[1,2], [3,4]]); ----------------------------- | cardinality([[1,2],[3,4]]) | ----------------------------- | 2 | ----------------------------- 1 row in set (0.01 sec)cardinality()只统计最外层的元素个数因此[[1,2], [3,4]]的结果是 2外层有两个子数组而不是 4。若需要统计内层子数组的元素个数可配合unnest表函数先展开再计算。作用于表列统计每行数组字段的长度CREATE TABLE user_tags ( user_id INT, tags ARRAYVARCHAR(20) ) DUPLICATE KEY(user_id) DISTRIBUTED BY HASH(user_id) BUCKETS 4 PROPERTIES (replication_num 1); INSERT INTO user_tags VALUES (1, [star, rock]), (2, [olap]), (3, NULL), (4, []); SELECT user_id, tags, cardinality(tags) AS tag_cnt FROM user_tags ORDER BY user_id;user_idtagstag_cnt1[star,rock]22[olap]13NULLNULL4[]0该示例同时展示了四种典型情况普通数组返回元素个数、单元素数组返回 1、数组为 NULL 时返回 NULL、空数组返回 0。与 array_length() 完全等价由于cardinality()是array_length()的别名以下两条语句返回完全一致的结果SELECT cardinality([10, 20, 30]); -- 3 SELECT array_length([10, 20, 30]); -- 3与 array_length() 的关系cardinality()与array_length()是互为别名的关系cardinality()文档中明确标注它是array_length()的别名array_length()文档中同样标注它有一个别名cardinality()见 array_length.md。两个函数在功能上没有任何差异你可以根据团队编码习惯或 SQL 可读性选择任意一个。它们在关键字索引keyword中也相互关联CARDINALITY, ARRAY_LENGTH, ARRAY。源码级实现原理核心实现基于 ArrayColumn 的 offsets 计算cardinality在 StarRocks BE后端中统一映射到向量化函数ArrayFunctions::array_length其实现位于 array_functions.cpp。核心逻辑如下StatusOrColumnPtr ArrayFunctions::array_length([[maybe_unused]] FunctionContext* context, const Columns columns) { DCHECK_EQ(1, columns.size()); RETURN_IF_COLUMNS_ONLY_NULL(columns); const size_t num_rows columns[0]-size(); const auto* col_array down_castconst ArrayColumn*(ColumnHelper::get_data_column(columns[0].get())); const auto arr_offsets col_array-offsets().immutable_data(); if (columns[0]-is_constant()) { // 常量列直接复用偏移量差构造 ConstColumn auto col_result Int32Column::create(); col_result-append(arr_offsets.data()[1]); auto const_column ConstColumn::create(std::move(col_result), num_rows); return const_column; } else { // 普通列逐行计算 offsets[i1] - offsets[i] int32_t* p col_result-get_data().data(); for (size_t i 0; i num_rows; i) { p[i] arr_offsets[i 1] - arr_offsets[i]; } if (arg0-has_null()) { // 复制 NULL 标记保持输入可空列的 null bitmap 不被修改 return NullableColumn::create(std::move(col_result), std::move(null_column)); } else { return col_result; } } }实现要点解读基于偏移量差计算StarRocks 的数组列以ArrayColumn表示内部通过offsetsUInt32Column记录每个数组在元素列中的起始位置。第i个数组的长度就是offsets[i1] - offsets[i]因此函数整体是 O(1) 的向量化逐行运算无需遍历数组元素本身常量列优化当输入是常量列如字面量[1,2,3]在列式执行中被物化为常量时只需计算一次长度然后构造ConstColumn广播到所有行避免重复计算NULL 语义的传递当输入列存在 NULL 时函数会复制输入的 null bitmap 到结果列从而保证输入为 NULL输出为 NULL的语义同时从源码注释和测试可以看出该函数不会修改输入可空列的 null bitmap返回值类型结果写入Int32Column对应 SQL 层面的INT返回类型。函数声明ArrayFunctions::array_length的向量化函数声明位于 array_functions.hDEFINE_VECTORIZED_FN(array_length);注册机制cardinality 同时支持 ARRAY 与 MAPStarRocks 的内置函数通过构建脚本 functions.py 集中注册。搜索该文件可以发现cardinality与array_length的注册记录# L1073: array_length 主注册支持 ANY_ARRAY返回 INT [150000, array_length, True, False, INT, [ANY_ARRAY], ArrayFunctions::array_length], # L1575-L1576: cardinality 是重载函数同时支持 MAP 与 ARRAY [170100, cardinality, True, False, INT, [ANY_MAP], MapFunctions::map_size], [170101, cardinality, True, False, INT, [ANY_ARRAY], ArrayFunctions::array_length],从这个注册信息可以得出两个重要结论cardinality是array_length的别名两者都指向同一个后端实现ArrayFunctions::array_length注册表150000与170101完全对应cardinality还是一个重载函数除了数组它还接受ANY_MAP类型的参数并返回 Map 的键值对个数此时映射到MapFunctions::map_size实现位于 map_functions.cpp同样通过 offsets 差分offsets[i1] - offsets[i]计算与数组的实现思路一致。也就是说SQL 中cardinality(...)会根据实参类型自动分发数组走ArrayFunctions::array_lengthMap 走MapFunctions::map_size。而array_length只接受数组。这也解释了为什么cardinality一词在数据库语境中常被用来表示集合的基数元素个数。测试验证StarRocks 为array_length/cardinality提供了完整的单元测试位于 array_functions_test.cpp 的TEST_F(ArrayFunctionsTest, array_length)用例中。测试覆盖了以下关键场景空数组[]→ 0NULL 输入数组本身为 NULL → 返回 NULL含 NULL 元素的数组[NULL]→ 1NULL 元素计入长度一维数值数组[1]→ 1[1,2]→ 2字符串数组[a]→ 1[a,b]→ 2嵌套数组[[NULL]]→ 1[[]]→ 1[[],[]]→ 2[[1],[2],[3]]→ 3不可变性测试断言array_length不会修改输入可空列的 null bitmap常量列优化路径测试构造ConstColumn输入验证常量列分支的正确性4 个元素的数组被广播为 3 行每行结果均为 4。此外array_length还被广泛用于 Lambda 高阶函数中例如 lambda_array_expr_test.cpp 展示了在array_map(b - array_length(a) b, a)这类嵌套 Lambda 表达式中作为公共子表达式提取的场景。典型应用场景cardinality()在实践中通常与其他数组函数配合使用1. 过滤空数组或 NULL 数组SELECT user_id, tags FROM user_tags WHERE cardinality(tags) 0;2. 与 array_agg() 结合统计分组后的元素个数SELECT dept_id, array_agg(emp_name) AS emp_names, cardinality(array_agg(emp_name)) AS emp_cnt FROM employees GROUP BY dept_id;3. 与 unnset/unnest 配合处理嵌套数组-- 统计多维数组中每个子数组的长度 SELECT t.sub_arr, cardinality(t.sub_arr) AS sub_len FROM (SELECT [[1,2],[3,4,5]] AS arr) a, UNNEST(a.arr) AS t(sub_arr);4. 在高阶函数中度量数组规模array_length/cardinality经常出现在array_map、array_filter、array_sort的 Lambda 表达式中用于依据数组长度进行映射、过滤或排序。注意事项与限制版本要求cardinality()从 StarRocks v3.0 起支持只统计第一层对于多维数组只返回最外层元素个数不会递归统计NULL 语义区分元素 NULL 计入长度数组本身为 NULL 时结果为 NULL返回类型始终返回INT不会溢出数组长度受 StarRocks 数组列 offsets 的UINT32表示约束与 array_length 等价两者可在 SQL 中互换使用对 Map 的扩展cardinality()对ANY_MAP参数同样有效返回键值对个数这是其与array_length的一个区别array_length仅支持数组。参考文档与源码函数文档cardinality.md、array_length.md后端实现array_functions.cpp、array_functions.hMap 扩展实现map_functions.cpp函数注册表functions.py、functions.py单元测试array_functions_test.cpp、lambda_array_expr_test.cpp【免费下载链接】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),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询