
StarRocks array_contains_all 函数详解判断数组包含关系的完整指南【免费下载链接】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/starrocksarray_contains_all是 StarRocks 提供的数组函数之一用于判断一个数组是否包含另一个数组的全部元素即子集关系常用于用户标签分析、权限校验、特征匹配等需要“多元素全命中”判断的场景。本文以官方 SQL 函数参考文档为主体结合 StarRocks 开源仓库中 BE 端的 C 向量化实现与单元测试系统讲解该函数的语法、参数约束、NULL 语义、性能实现原理与实战示例帮助读者在真实查询中正确、高效地使用它。函数概述array_contains_all(arr1, arr2)用于检查arr1是否包含arr2的所有元素即arr2是否为arr1的子集是子集时返回1不是子集时返回0两个数组中的任意一个为NULL时返回NULL。该函数与单元素包含判断函数array_contains的区别在于array_contains_all是一次性的“全量包含”判断等价于对arr2中的每个元素逐一执行包含检查并取逻辑与但底层通过哈希表实现比逐元素调用array_contains效率更高详见下文“底层实现原理”一节。语法BOOLEAN array_contains_all(arr1, arr2)参数说明参数说明arr1待检查的源数组即“被包含方”的容器。arr2目标数组函数检查arr2是否为arr1的子集。约束条件两个数组中元素的数据类型必须一致支持的元素类型以 StarRocks 的 ARRAY 类型文档 为准。关于 ARRAY 类型需要了解的基础约束来自 ARRAY 类型文档支持的元素类型包括BOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、VARCHAR、CHAR、DATETIME、DATE、JSON以及自 v3.1 起的ARRAY、MAP、STRUCT嵌套类型数组元素默认可为 NULL例如[null, 1, 2]数组列本身可用NOT NULL约束ARRAY 列不能作为 key 列、分区键或分桶键从 v2.1 起 ARRAY 列可在 Primary Key、Unique Key、Aggregate 等表中使用Aggregate 表中仅支持replace()或replace_if_not_null()聚合方式。返回值返回BOOLEAN类型arr2是arr1的子集时返回1否则返回0两个数组中的任意一个为NULL时返回NULL。使用注意事项如果数组中包含null元素null会被当作一个普通值参与包含判断而非视为“未知”。也就是说[null]是[1, 2, null]的子集返回1空数组是任何数组的子集array_contains_all(arr1, [])恒返回1两个数组中元素的出现顺序可以不同包含判断与顺序无关。示例完整实战流程1. 建表并插入数据创建一张名为t1的 OLAP 表包含两个ARRAYINT列然后插入 6 行覆盖各种边界情况的数据CREATE TABLE t1 ( c0 INT, c1 ARRAYINT, c2 ARRAYINT ) ENGINEOLAP DUPLICATE KEY(c0) DISTRIBUTED BY HASH(c0); INSERT INTO t1 VALUES (1,[1,2,3],[1,2]), (2,[1,2,3],[1,4]), (3,NULL,[1]), (4,[1,2,null],NULL), (5,[1,2,null],[null]), (6,[2,3],[]);其中第 3 行c1为NULL第 4 行c2为NULL第 5 行两个数组均包含null元素第 6 行c2是空数组——这三类数据分别对应了返回值中的三种特殊语义。2. 查询原始数据SELECT * FROM t1 ORDER BY c0; ---------------------------- | c0 | c1 | c2 | ---------------------------- | 1 | [1,2,3] | [1,2] | | 2 | [1,2,3] | [1,4] | | 3 | NULL | [1] | | 4 | [1,2,null] | NULL | | 5 | [1,2,null] | [null] | | 6 | [2,3] | [] | ----------------------------3. 判断每行c2是否为c1的子集SELECT c0, c1, c2, array_contains_all(c1, c2) FROM t1 ORDER BY c0; -------------------------------------------------------- | c0 | c1 | c2 | array_contains_all(c1, c2) | -------------------------------------------------------- | 1 | [1,2,3] | [1,2] | 1 | | 2 | [1,2,3] | [1,4] | 0 | | 3 | NULL | [1] | NULL | | 4 | [1,2,null] | NULL | NULL | | 5 | [1,2,null] | [null] | 1 | | 6 | [2,3] | [] | 1 | --------------------------------------------------------结果逐行解读第 1 行c2 [1,2]是c1 [1,2,3]的子集返回1第 2 行c2 [1,4]中的4不在c1中不是子集返回0第 3 行c1为NULL返回NULL第 4 行c2为NULL返回NULL第 5 行两个数组都包含nullnull被当作普通值参与判断[null]是[1,2,null]的子集返回1第 6 行c2是空数组空数组被视为任何数组的子集返回1。支持的输入类型从 StarRocks 的函数注册表gensrc/script/functions.py可以看到array_contains_all除通用注册外还针对具体元素类型做了特化注册每个特化版本都绑定到对应的array_contains_all_specificTYPE_XXX模板实例输入数组元素类型绑定的 BE 实现ARRAY_BOOLEANArrayFunctions::array_contains_all_specificTYPE_BOOLEANARRAY_TINYINT/ARRAY_SMALLINT/ARRAY_INT/ARRAY_BIGINT/ARRAY_LARGEINT对应整数类型的array_contains_all_specificARRAY_DECIMALV2/ARRAY_DECIMAL32/ARRAY_DECIMAL64/ARRAY_DECIMAL128对应十进制类型的特化实现ARRAY_FLOAT/ARRAY_DOUBLE对应浮点类型的特化实现ARRAY_VARCHAR字符串数组的特化实现ARRAY_DATE/ARRAY_DATETIME时间类型数组的特化实现ANY_ARRAY任意类型通用入口ArrayFunctions::array_contains_all也就是说整数、字符串、日期、时间、十进制、浮点等主流标量类型数组均得到直接支持同时通用入口可覆盖任意数组类型包括嵌套 ARRAY、MAP、STRUCT 等复合类型场景。底层实现原理哈希表驱动的向量化判断在 StarRocks BE 端array_contains_all的声明位于 be/src/exprs/array_functions.h核心实现位于 be/src/exprs/array_functions.tpp 中的模板类ArrayContainsAll。从源码结构可以梳理出以下关键设计哈希表加速查找源码注释明确指出“for array_contains_all, we build hash table to speed up the search.”对array_contains_all构建哈希表以加速查找。实现使用phmap::flat_hash_mapbe/src/exprs/array_functions.tpp把一侧数组的元素建成哈希表再用另一侧数组的元素去查表将包含判断从逐元素线性扫描的 O(n×m) 降为近似 O(nm)与逐元素调用array_contains相比大幅减少了重复建表开销。用哪一侧建表智能选择array_contains_all的建表侧并不固定。在prepare阶段be/src/exprs/array_functions.tpp实现会检查两个输入是否为常量列并“prefer to use the left column to build hash table”优先用左列建表如果只有右列是常量则退而用右列建表。当两侧都是常量时直接在prepare阶段就算出结果并缓存state-contains运行时process阶段直接复用该常量结果be/src/exprs/array_functions.tpp避免重复计算。在_process_with_hash_tablebe/src/exprs/array_functions.tpp中通过模板参数HTFromLeft区分两种方向哈希表来自左列右列所有元素都必须在哈希表中命中否则返回false哈希表来自右列借助BitMask记录右列元素在左列中的命中覆盖情况必须全部命中且 NULL 出现情况一致才返回true。这种“小表建哈希、大表查哈希”的方向选择在常量折叠场景下尤其有效。NULL 的两种语义被严格区分实现中把“数组本身为 NULL”和“数组元素为 null”分开处理数组本身为 NULL在process入口通过RETURN_IF_COLUMNS_ONLY_NULL(columns)及对可空列的判空逻辑be/src/exprs/array_functions.tpp处理结果为NULL元素为 null建表阶段单独记录state-has_nullbe/src/exprs/array_functions.tppnull不进入哈希表但作为“特殊值”参与判断目标数组出现null时要求源数组也含有null这与文档中“null被当作普通值”的语义完全一致。此外单元测试 be/test/exprs/array_functions_test.cpp 覆盖了包含 NULL 数组、NULL 元素、字符串数组、嵌套数组等多种组合例如array_contains_all([a, b, NULL], [NULL])→1array_contains_all([a, b, c], NULL)→NULLarray_contains_all([a, b, c], [a, d])→0与本文示例中验证的语义一一对应。相关函数与延伸阅读若只需判断单个元素是否存在可使用array_contains(arr, element)判断两个数组是否存在交集可参考array_intersect等集合类数组函数ARRAY 类型的完整定义、建表限制与元素访问方式见 ARRAY 类型文档全部数组函数清单可在 docs/en/sql-reference/sql-functions/array-functions 目录下查看。总结array_contains_all(arr1, arr2)是 StarRocks 中进行“子集包含”判断的高效工具它把null元素作为普通值参与比较、把空数组视为任何数组的子集、对数组本身为NULL时返回NULL语义清晰且边界行为经过单元测试固化。在 BE 端该函数基于phmap哈希表实现并结合常量列折叠与智能建表侧选择进行优化适合在用户标签匹配、特征集合校验、多条件过滤等 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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考