首页 / 工具 / 迁移清单 / MaxCompute → StarRocks
MaxCompute 迁移到 StarRocks 的函数改写清单
从 MaxCompute 迁移到 StarRocks 时,在 MaxCompute 有对应写法的 45 个常用函数中,18 个需要改写(其中 1 个在 StarRocks 没有对应函数)。逐个列出两边写法和注意事项。
需要改写的函数 · 迁移注意事项 · 可以直接用的函数 · 反向:StarRocks 迁移到 MaxCompute
需要改写的函数
| 函数 | MaxCompute 写法 | StarRocks 写法 | StarRocks 说明 |
|---|---|---|---|
| APPROX_COUNT_DISTINCT | APPROX_DISTINCT(colname) | 支持 APPROX_COUNT_DISTINCT(expr) | 结果近似于 COUNT(DISTINCT col),使用固定大小的内存,适合高基数列。 |
| COLLECT_LIST | COLLECT_LIST(colname) | 需改写 ARRAY_AGG(col [ORDER BY ...]) | 在 StarRocks 文档中搜索不到 COLLECT_LIST。ARRAY_AGG 会保留 NULL,3.0 起支持 ORDER BY 指定元素顺序。 |
| COLLECT_SET | COLLECT_SET(colname) | 需改写 ARRAY_AGG(DISTINCT col) | 在 StarRocks 文档中搜索不到 COLLECT_SET。ARRAY_AGG_DISTINCT 是 ARRAY_AGG(DISTINCT) 的别名。ARRAY_AGG 会保留 NULL。 |
| DATEADD | DATEADD(date, delta, datepart) | 需改写 TIMESTAMPADD(unit, n, datetime_expr) | 单位写成关键字,例如 HOUR、DAY、MONTH,不加引号。TIMESTAMPADD 文档没有列出 QUARTER;按季度加减可以用 DATE_ADD(dt, INTERVAL n QUARTER)。 |
| DATETRUNC | DATETRUNC(date, date_part) | 需改写 date_trunc('month', datetime) | 单位在前且必须是常量。DATE 输入只能截断到 year、quarter、month、week、day。 |
| DECODE | DECODE(expression, search, result[, search, result]...[, default]) | 需改写 CASE expr WHEN search THEN result ... ELSE default END | 函数列表中没有按值匹配的 DECODE,只有 base64、hex 等解码函数,用 CASE 改写。 |
| EXPLODE | EXPLODE(var) | 需改写 FROM t, UNNEST(arr) AS u(x) | UNNEST 是表函数,配合横向连接使用,不需要写 LATERAL。NULL 或空数组不输出行;3.2.7 起可以用 LEFT JOIN ... ON TRUE 保留这些行。 |
| FROM_JSON | from_json(jsonStr, schema) | 需改写 parse_json(str) | 没有 FROM_JSON。parse_json 返回 JSON 类型,而不是 STRUCT 或 MAP。字符串不是合法 JSON 时返回 NULL。取字段可以接 json_query 或 -> 运算符。 |
| GETDATE | GETDATE() | 别名 NOW([p]) | 别名有 current_timestamp、localtime 和 localtimestamp,返回 DATETIME,默认精度到秒。3.1.6 起可以传 1~6 指定秒后的小数位数。结果受时区设置影响。 |
| LENGTH | LENGTH(str) | 需改写 char_length(str) | LENGTH 返回的是字节数。按字符计数要用 char_length,别名 character_length,目前只支持 UTF-8。 |
| MAX_PT | MAX_PT(table_full_name) | 不支持 | 在 StarRocks 官方文档中搜索不到 MAX_PT。改写为 WHERE pt = (SELECT MAX(pt) FROM t)。 |
| MONTHS_BETWEEN | MONTHS_BETWEEN(end_date, start_date) | 需改写 months_diff(expr1, expr2) | 函数列表中没有 MONTHS_BETWEEN。months_diff 返回 expr1 减 expr2 的月数,类型是 BIGINT,只精确到月;日期不存在时返回 NULL。 |
| NVL | NVL(value, default_value) | 需改写 IFNULL(expr1, expr2) | 条件函数列表中没有 NVL,只有 case、coalesce、if、ifnull 和 nullif。IFNULL 的结果类型与 expr1 一致。 |
| SIZE | SIZE(array_or_map) | 别名 array_length(arr) / map_size(m) | 数组用 array_length,别名 cardinality,3.0 起提供,NULL 元素也计入长度,输入为 NULL 时返回 NULL。Map 用 map_size,2.5 起提供,别名同样是 cardinality。 |
| SORT_ARRAY | SORT_ARRAY(a[, isasc]) | 需改写 array_sort(array) | 升序排列,NULL 放在开头。4.0 起可以传 Lambda 比较函数自定义顺序。 |
| TO_CHAR | TO_CHAR(date, format) | 需改写 DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') | 没有 TO_CHAR。DATE_FORMAT 使用 MySQL 风格格式符,%i 表示分钟。结果超过 128 字节时返回 NULL。 |
| TO_DATE | TO_DATE(date_str[, format]) | 需改写 str_to_date(str, format) | StarRocks 的 to_date 只接受 DATETIME 并取日期部分,不能解析字符串。按格式解析用 str_to_date,格式符与 date_format 相同;格式只含日期时返回 DATE,否则返回 DATETIME。 |
| WM_CONCAT | WM_CONCAT(separator, colname) | 需改写 GROUP_CONCAT([DISTINCT] expr [ORDER BY ...] [SEPARATOR sep]) | 默认分隔符是逗号,跳过 NULL。结果长度受 group_concat_max_len 限制,默认 1,024 个字符,超出部分会被截断。 |
迁移注意事项
APPROX_COUNT_DISTINCT 近似去重计数
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
COLLECT_LIST 聚合为数组
- 不要依赖数组元素的顺序。MaxCompute 文档建议用 SORT_ARRAY 排序;StarRocks 可以直接写 ARRAY_AGG(x ORDER BY y)。
- 用 COLLECT_LIST(x)[0] 取每组的一个值时,MaxCompute 官方建议改用 ANY_VALUE,性能更好,语义也更清楚。
- StarRocks 的 ARRAY_AGG 保留 NULL,MaxCompute 和 Doris 的 COLLECT_LIST 丢弃 NULL,数组长度可能不一致。
COLLECT_SET 去重聚合为数组
- NULL 的处理不同:MaxCompute、Doris 会丢弃 NULL,StarRocks 的 ARRAY_AGG 会保留 NULL。迁移到 StarRocks 后数组里可能多出 NULL 元素。
DATEADD 按单位加减日期
- MaxCompute 和 Hologres 中 mm 表示月,mi 表示分钟。把 DATEADD(d, 1, 'mm') 当成加 1 分钟,是迁移时最常见的错误。
- Spark 3.4.0 起的 dateadd(d, 1) 表示加 1 天,参数个数和含义都与 MaxCompute 不同,不能直接照搬。
- MaxCompute 的 DATEADD 遇到 date 为 NULL 会报错,而不是返回 NULL。字段可能为空时,先过滤或用 IF 包一层。
- MaxCompute 按月加减时,如果目标月份没有对应日期,结果取当月最后一天。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
- 周的起点:MaxCompute 的 week 默认从周一开始,Doris 和 Spark 文档的示例也截断到周一。按周汇总前确认业务定义的周起点。
DECODE 多值匹配
- MaxCompute 的 DECODE 把 NULL 和 NULL 视为相等,DECODE(x, NULL, 0, 1) 在 x 为 NULL 时返回 0。改写成 CASE x WHEN NULL THEN 0 ... 永远不会匹配,要写成 CASE WHEN x IS NULL THEN 0 ...。
- Hive 和 Flink 也有 DECODE,但含义是字符集解码。把 MaxCompute 的多参数 DECODE 原样搬过去会报参数错误,必须改写成 CASE。
- MaxCompute 要求所有 result 类型一致,例如 DECODE(x, 1, 1, 2, 'b') 会报错。改写成 CASE 后各引擎的隐式转换规则不同,建议显式 CAST。
EXPLODE 数组展开为多行
- 空数组和 NULL 数组的行会被直接丢掉:MaxCompute、Doris 的 EXPLODE 和 StarRocks 的 UNNEST 都是这样。需要保留时,Doris 和 Spark 用 EXPLODE_OUTER,StarRocks 3.2.7 起用 LEFT JOIN UNNEST(...) ON TRUE。
- MaxCompute 的 EXPLODE 不能和其他列写在同一个 SELECT 里。需要同时取其他列时,要改成 LATERAL VIEW 写法。
FROM_JSON 按 schema 解析 JSON
- MaxCompute 的 from_json 解析成 FLOAT、DOUBLE 或 DECIMAL 时不保证精度。金额类字段建议先按 STRING 取出,再 CAST 成 DECIMAL。
- StarRocks 的 parse_json 和 Doris 的 JSON_PARSE 返回的是 JSON 类型,下游需要 STRUCT 或 MAP 时要再做一次转换,不能直接替换 from_json。
- 非法 JSON 的处理不同:StarRocks 的 parse_json 返回 NULL,Doris 的 JSON_PARSE 直接报错。脏数据较多的表,在 Doris 中改用 JSON_PARSE_ERROR_TO_NULL。
- MaxCompute 的 STRUCT key 区分大小写。JSON 里是 userId、schema 里写成 userid 时,取到的是 NULL,并且不会报错。
GETDATE 获取当前时间
- MaxCompute 的 GETDATE 固定使用东八区,其他引擎的结果取决于会话或集群时区。迁移后如果时间差了 8 小时,先检查时区设置。
- 返回类型不同:MaxCompute、StarRocks 和 Doris 返回 DATETIME,Hologres 的 NOW 带时区(文档把不带时区的版本单独列为 LOCALTIMESTAMP),Flink 返回 TIMESTAMP_LTZ(3)。直接写入字符串或 DATETIME 字段时,格式可能变化。
- 精度不同:MaxCompute 默认到秒,StarRocks 和 Doris 默认到秒、可传参数到微秒,Flink 到毫秒。用当前时间做去重或比较时要注意小数部分。
LENGTH 字符串长度
- StarRocks 和 Doris 的 LENGTH 返回字节数。像 WHERE LENGTH(name) > 10 这样的条件,迁移后对中文内容会多筛出很多行,而且不会报错。
- 按字符计数统一写 CHAR_LENGTH 最稳妥:Hologres、StarRocks、Doris、Flink 都支持,Hive 2.2.0 起也支持(char_length 是 character_length 的简写)。
- MaxCompute 的 LENGTH 遇到非 UTF-8 编码的字符串返回 -1,不是 NULL。
MAX_PT 取最新分区
- MaxCompute 的 MAX_PT 只看一级分区。多级分区表官方建议直接用子查询。
- MaxCompute 中用 ALTER TABLE 建出的空分区不参与计算;所有分区都为空时会报错。MaxCompute 没有 MIN_PT,取最小分区用 MIN(pt) 子查询。
- MaxCompute 官方给出的等价写法是 WHERE pt = (SELECT MAX(pt) FROM tbl),可以直接用于其他引擎。改写后的子查询需要扫描分区列,表很大时确认目标引擎能做分区裁剪。
MONTHS_BETWEEN 相差月数
- StarRocks 的 months_diff、Flink 的 TIMESTAMPDIFF 和 Hologres 的 EXTRACT 写法都只返回整数月,原 SQL 中依赖小数部分的计算(例如按 0.5 个月判断)需要重新设计。
- 舍入不同:Hive 和 Spark 默认保留 8 位小数,MaxCompute 返回完整的 DOUBLE,Doris 由 round_type 控制。和原结果做等值比较前,先统一 ROUND。
NVL 空值替换
- MaxCompute 文档要求两个参数类型一致,例如 NVL(bigint_col, 0.0) 应先做 CAST。文档自带的示例里又有 datetime 列配字符串默认值的写法,两处说法不一致,建议实测。
- 迁移到 Hologres、StarRocks 或 Flink SQL 时,统一改写为 COALESCE 最省事,因为 COALESCE 在七个引擎中都可用。
SIZE 数组和 Map 元素个数
- StarRocks 和 Doris 区分数组和 Map 函数。从 MaxCompute 或 Hive 迁移时,要按字段类型分别改成 array_length、map_size 或 ARRAY_SIZE、MAP_SIZE。
- StarRocks 和 Doris 文档写明 NULL 元素也计入个数。需要只统计非空元素时,要先过滤再计数。
SORT_ARRAY 数组排序
- Spark 有两个排序函数:sort_array 升序时把 NULL 放在开头,array_sort 把 NULL 放在末尾。从 MaxCompute 或 Hive 迁移时应使用 sort_array,结果才一致。
- 降序的写法不同:MaxCompute 和 Spark 传第二个参数,Flink 传 ascending_order,Doris 用 ARRAY_REVERSE_SORT,Hive 和 Hologres 的函数只能升序。
TO_CHAR 日期转字符串
- MaxCompute 的 'yyyy-mm-dd' 原样搬到 Hive、Spark 或 Flink,mm 会被当成分钟,结果类似 2026-30-14,而且不会报错。Java 风格要写 'yyyy-MM-dd'。
- StarRocks 和 Doris 的分钟是 %i,不是 %M。%M 表示英文月份名。
- MaxCompute 的 TO_CHAR 遇到 date 为 NULL 会报错,而不是返回 NULL。
TO_DATE 字符串转日期
- 同名不同义:把 MaxCompute 的 TO_DATE('20261013', 'yyyymmdd') 直接搬到 StarRocks、Doris 或 Hive 会报错或得到错误结果,需要改用 str_to_date 或 unix_timestamp。
- MaxCompute 传入 format 时返回 DATETIME 而不是 DATE。和 DATE 类型字段比较或写入 DATE 列时,注意类型转换。
- MaxCompute 的格式符里 mm 是月、mi 是分钟;Spark 和 Flink 里 MM 是月、mm 是分钟。
- MaxCompute 的日期字符串位数不对时返回 NULL,例如 '2025112' 配 'yyyymmdd'。
WM_CONCAT 分组拼接字符串
- StarRocks 的 GROUP_CONCAT 默认最多 1,024 个字符,超出部分不报错直接截断。长列表需要先调大 group_concat_max_len。
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY ...),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
- StarRocks 3.0.6 和 3.1.3 起,GROUP_CONCAT 必须用 SEPARATOR 关键字声明分隔符。
可以直接用的函数
下面 27 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。
- ADD_MONTHS 按月加减
- ANY_VALUE 取组内任意值
- ARRAY_CONTAINS 判断数组是否包含元素
- COALESCE 取第一个非空值
- CONCAT 字符串拼接
- CONCAT_WS 按分隔符拼接
- DATE_ADD 日期加减
- DATE_FORMAT 日期格式化
- DATE_SUB 日期减天数
- DATEDIFF 日期差
- DAYOFWEEK 星期几
- FROM_UNIXTIME 时间戳转日期
- GET_JSON_OBJECT 提取 JSON 字段
- IF 条件判断
- INSTR 查找子串位置
- LAST_DAY 当月最后一天
- MAX_BY 取最大值对应的列
- PERCENTILE_APPROX 近似分位数
- REGEXP_EXTRACT 正则提取
- REGEXP_REPLACE 正则替换
- SPLIT 字符串拆分
- SPLIT_PART 按分隔符取第 N 段
- STR_TO_MAP 字符串转 Map
- SUBSTR 截取子串
- SUBSTRING_INDEX 按分隔符截取
- UNIX_TIMESTAMP 日期转时间戳
- WEEKOFYEAR 一年中的第几周