首页 / 工具 / 迁移清单 / Hologres → MaxCompute
Hologres 迁移到 MaxCompute 的函数改写清单
从 Hologres 迁移到 MaxCompute 时,在 Hologres 有对应写法的 43 个常用函数中,19 个需要改写,另有 8 个可以改用 MaxCompute 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:MaxCompute 迁移到 Hologres
需要改写的函数
| 函数 | Hologres 写法 | MaxCompute 写法 | MaxCompute 说明 |
|---|---|---|---|
| ADD_MONTHS | d + interval '1 month' | 支持 ADD_MONTHS(startdate, num_months) | 返回 yyyy-mm-dd 格式的 STRING,不是 DATE。格式不对时返回 NULL,例如 '20170214'。 |
| APPROX_COUNT_DISTINCT | APPROX_COUNT_DISTINCT(column) | 别名 APPROX_DISTINCT(colname) | MaxCompute 2.0 扩展函数,返回 BIGINT,文档写明会有 5% 的误差。 |
| COLLECT_LIST | ARRAY_AGG(expression) | 支持 COLLECT_LIST(colname) | 值为 NULL 的行不参与计算,结果不保证顺序。官方建议拼接字符串时改用 WM_CONCAT。 |
| COLLECT_SET | ARRAY_AGG(DISTINCT expression) | 支持 COLLECT_SET(colname) | 返回去重后的数组,值为 NULL 的行不参与计算。 |
| DATE_ADD | DATEADD(d, num, 'day') | 支持 DATE_ADD(startdate, delta) | 按天加减,delta 为负数时表示减。返回 DATE,输入的时间部分会被丢弃。需要按月、小时等单位加减时用 DATEADD。 |
| DATE_FORMAT | TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') | 支持 DATE_FORMAT(date, format) | 返回 STRING。默认模式下分钟写 mi,写 mm 会输出月份;开启 Hive 兼容模式后分钟写 mm,写 mi 返回 NULL。DATE 和 STRING 输入需要开启 Hive 兼容模式。 |
| DATE_SUB | d - interval '1 day' | 支持 DATE_SUB(startdate, delta) | delta 大于 0 时减,小于 0 时加。返回 DATE,输入的时间部分会被丢弃。startdate 为 NULL 时报错,delta 为 NULL 时返回 NULL。 |
| DATETRUNC | DATE_TRUNC('month', ts) | 支持 DATETRUNC(date, date_part) | 返回类型与输入相同。单位支持 yyyy、q、mm、week、isoweek、dd、hh、mi、ss、ff3,week 默认从周一开始,也可以写 week(sunday)。 |
| EXPLODE | UNNEST(anyarray) | 支持 EXPLODE(var) | 支持 array 和 map。同一个 SELECT 只能有一个 EXPLODE,也不能同时选其他列,不能与 GROUP BY 等一起使用。数组为 NULL 时不输出行。 |
| FROM_JSON | json_str::jsonb ->> 'key' | 支持 from_json(jsonStr, schema) | schema 写法与建表时的类型一致,例如 'a bigint, b double'、'array<bigint>'、'map<string,string>'。返回 ARRAY、MAP 或 STRUCT。STRUCT 的 key 区分大小写,缺失的 key 返回 NULL,类型不匹配的值会被忽略。 |
| FROM_UNIXTIME | TO_TIMESTAMP(seconds) | 支持 FROM_UNIXTIME(unixtime) | 输入为秒,返回 DATETIME。默认只接受一个参数;开启 Hive 兼容模式后可以传第二个参数指定格式。 |
| GETDATE | NOW() 或 CURRENT_TIMESTAMP | 支持 GETDATE() | 返回 DATETIME,以东八区时间为标准。同一条 SQL 中总是返回固定值,精度到秒;开启 2.0 数据类型后精度到毫秒。 |
| INSTR | STRPOS(str, substr) | 支持 INSTR(str1, str2[, start_position[, nth_appearance]]) | 找不到时返回 0,str2 为空串时返回 1,任一参数为 NULL 时返回 NULL。start_position 为负数时从末尾倒数,nth_appearance 必须大于 0。 |
| PERCENTILE_APPROX | APPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col) | 支持 PERCENTILE_APPROX(col[, weight], p[, B]) | MaxCompute 2.0 扩展函数。p 取 0~1,也可以传数组一次求多个分位数。B 是精度参数,默认 10000。可选的 weight 参数为每行指定权重。col 为 NULL 的行不参与计算,p 或 B 为 NULL 时报错。 |
| REGEXP_EXTRACT | (REGEXP_MATCH(str, pattern))[n] | 支持 REGEXP_EXTRACT(source, pattern[, group_id]) | group_id 默认为 1,为 0 时返回整个匹配。pattern 没有分组且不传 group_id 时会报错。Hive 兼容数据类型版本遵循 Java 正则规范,1.0 和 2.0 数据类型版本遵循 MaxCompute 自己的规范。 |
| SIZE | ARRAY_LENGTH(arr, 1) | 支持 SIZE(array_or_map) | 同一个函数可以处理 ARRAY 和 MAP,返回 INT。 |
| SORT_ARRAY | ARRAY_SORT(anyarray) | 支持 SORT_ARRAY(a[, isasc]) | isasc 默认为 True,即升序,传 False 时降序。NULL 视为最小值。 |
| SPLIT | REGEXP_SPLIT_TO_ARRAY(str, pattern) | 支持 SPLIT(source, delimiter[, trimTailEmpty]) | 返回 ARRAY<STRING>。分隔符支持正则表达式。trimTailEmpty 默认为 true,会去掉末尾的空字符串。任一参数为 NULL 时返回 NULL。 |
| WM_CONCAT | STRING_AGG(expression, delimiter) | 支持 WM_CONCAT(separator, colname) | 分隔符必须是常量且写在前面。支持 DISTINCT 和 WITHIN GROUP (ORDER BY ...),值为 NULL 的行不参与计算。 |
可以改用原生函数
下面的函数在 Hologres 中只能用替代写法,MaxCompute 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Hologres 写法 | MaxCompute 写法 | MaxCompute 说明 |
|---|---|---|---|
| ANY_VALUE | MAX(col) | 支持 ANY_VALUE(colname) | 值为 NULL 的行不参与计算,不保证返回哪一行。 |
| DAYOFWEEK | EXTRACT(DOW FROM ts) + 1 | 支持 DAYOFWEEK(date) | 返回 1~7,1 是周日,7 是周六。WEEKDAY(date) 则以周一为 0、周日为 6。 |
| DECODE | CASE expr WHEN search THEN result ... ELSE default END | 支持 DECODE(expression, search, result[, search, result]...[, default]) | 没有匹配且没有 default 时返回 NULL。所有 result 的类型必须一致,search 与 expression 的类型也必须一致,否则报错。在 DECODE 中 NULL 与 NULL 视为相等。 |
| MONTHS_BETWEEN | (EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b) | 支持 MONTHS_BETWEEN(end_date, start_date) | 返回 DOUBLE,end_date 晚于 start_date 时为正。两个日期都是月末时返回整数,否则按天数差除以 31 折算。 |
| NVL | COALESCE(value, default_value) | 支持 NVL(value, default_value) | 文档要求两个参数的数据类型一致。 |
| SUBSTR | SUBSTRING(str FROM start FOR len) | 支持 SUBSTR(str, start_position[, length]) | 从 1 开始计数,负数从末尾倒数。start_position 为 0 时返回空字符串;Hive 兼容模式和 BigQuery 兼容模式下按 1 处理。length 为 0 或负数时返回空字符串。 |
| UNIX_TIMESTAMP | EXTRACT(EPOCH FROM ts) | 支持 UNIX_TIMESTAMP(date) | 输入可以是 DATETIME、DATE、TIMESTAMP 或固定格式的字符串,返回秒级 BIGINT,小数秒会被丢弃。不支持格式参数。新类型系统下字符串需要先 CAST 为 DATETIME。 |
| WEEKOFYEAR | EXTRACT(WEEK FROM ts) | 支持 WEEKOFYEAR(date[, date_part]) | 默认周一为一周的第一天,1 月 1 日所在周有 4 天及以上属于当年时算作第一周。date_part 可以传 week(sunday) 等指定一周的起始日,或传 isoweek。 |
迁移注意事项
ADD_MONTHS 按月加减
- MaxCompute 返回字符串,Hive 4.0.0 之前也会丢掉时间部分。结果和 DATE 或 DATETIME 字段比较时,注意类型转换。
- Hologres 和 Flink 的月末行为文档没有写明,迁移涉及月末日期时建议用已知数据核对。
APPROX_COUNT_DISTINCT 近似去重计数
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
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 元素。
DATE_ADD 日期加减
- MaxCompute 的 DATE_ADD 返回 DATE,DATE_ADD(DATETIME '2005-02-28 10:00:00', 1) 的结果不带时间。需要保留时间时改用 DATEADD(d, 1, 'dd'),它的返回类型与输入相同。
- MaxCompute 的 DATEADD 按月加时,目标月份没有对应日期会返回当月最后一天,例如 1 月 29 日加 1 个月得到 2 月 28 日。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
DATE_FORMAT 日期格式化
- 四套格式符不能混用:Java 风格写 yyyy-MM-dd HH:mm:ss,MySQL 风格写 %Y-%m-%d %H:%i:%s,PostgreSQL 风格写 YYYY-MM-DD HH24:MI:SS,MaxCompute 默认模式写 yyyy-mm-dd hh:mi:ss。
- 从 MaxCompute 默认模式迁出时,hh:mi:ss 要改成目标引擎的分钟写法。原样照搬到 Spark 或 Flink,mi 不会被识别为分钟。
- Hologres 的 HH 默认是 12 小时制,下午的时间会少 12 小时,必须写 HH24。
DATE_SUB 日期减天数
- MaxCompute 的 DATE_SUB 返回 DATE,会丢掉时间部分。需要保留时间时改用 DATEADD(d, -1, 'dd')。
- MaxCompute 的 DATE_SUB 遇到 startdate 为 NULL 会报错,而不是返回 NULL。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
- 周的起点:MaxCompute 的 week 默认从周一开始,Doris 和 Spark 文档的示例也截断到周一。按周汇总前确认业务定义的周起点。
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。
- MaxCompute 的 STRUCT key 区分大小写。JSON 里是 userId、schema 里写成 userid 时,取到的是 NULL,并且不会报错。
FROM_UNIXTIME 时间戳转日期
- 返回类型不同:MaxCompute 返回 DATETIME,Hologres 的 TO_TIMESTAMP 返回 TIMESTAMPTZ,其他引擎返回字符串。拿结果做日期计算前,确认是否需要再转换类型。
GETDATE 获取当前时间
- MaxCompute 的 GETDATE 固定使用东八区,其他引擎的结果取决于会话或集群时区。迁移后如果时间差了 8 小时,先检查时区设置。
- 返回类型不同:MaxCompute、StarRocks 和 Doris 返回 DATETIME,Hologres 的 NOW 带时区(文档把不带时区的版本单独列为 LOCALTIMESTAMP),Flink 返回 TIMESTAMP_LTZ(3)。直接写入字符串或 DATETIME 字段时,格式可能变化。
- 精度不同:MaxCompute 默认到秒,StarRocks 和 Doris 默认到秒、可传参数到微秒,Flink 到毫秒。用当前时间做去重或比较时要注意小数部分。
INSTR 查找子串位置
- MaxCompute 的三参数和四参数写法,例如 INSTR(s, 'e', 3, 2),在 StarRocks、Doris、Hive、Spark 和 Flink 中都没有对应写法。只传起始位置时可以改成 LOCATE,取第 N 次出现时需要改写成多步计算。
- Hologres 的 INSTR 依赖 orafce 扩展。没有安装扩展时 SQL 会报函数不存在,改用 STRPOS 即可。
- 子串为空串时,MaxCompute 和 Doris 文档写明返回 1,其他引擎文档没有说明。用 INSTR(s, x) > 0 判断包含关系时,x 可能为空串的场景要单独处理。
PERCENTILE_APPROX 近似分位数
- 第三个参数含义不同:MaxCompute 和 Hive 的 B、Spark 的 accuracy 都默认 10000;StarRocks 和 Doris 的 compression 只接受 2048~10000。从 Spark 迁移时,如果写了大于 10000 的 accuracy,要调整到这个范围内。
- MaxCompute 有带 weight 的四参数写法,例如 PERCENTILE_APPROX(col, weight, 0.5),其他引擎没有对应参数。迁移时要先确认第二个参数是权重还是分位点。
- 各引擎的算法不同,结果不会完全一致。MaxCompute 文档写明 p 落在两个值中间时取两者均值,Spark 返回满足条件的最小值,Flink 的 PERCENTILE 用线性插值。P50、P99 这类指标迁移后要实测对比。
- Hologres 的 APPROX_PERCENTILE 需要 V3.1 及以上版本,而且只抽样 8,192 个元素。数据量很大时,尾部分位数(例如 P999)的误差可能偏大。
REGEXP_EXTRACT 正则提取
- 第三个参数是否必填不一样:MaxCompute、Spark 和 Flink 可以省略,默认取第 1 组;StarRocks、Doris 和 Hive 必须写上。迁移时统一写出分组下标最稳妥。
- 没有匹配时的返回值不同:StarRocks 和 Doris 文档写明返回空字符串,MaxCompute 只写明参数为 NULL 时返回 NULL。下游用 IS NULL 判断的逻辑迁移后要实测。
- MaxCompute 的 pattern 没有分组且不传 group_id 时直接报错,例如 REGEXP_EXTRACT('foothebar', 'thebar')。要么给 pattern 加括号,要么传 0。
- 反斜杠转义各引擎不同。MaxCompute 文档要求在客户端写两个反斜杠,Spark 文档建议用 r'' 原始字符串。示例里用 [0-9] 代替 \d,可以避开转义差异。
SIZE 数组和 Map 元素个数
- StarRocks 和 Doris 区分数组和 Map 函数。从 MaxCompute 或 Hive 迁移时,要按字段类型分别改成 array_length、map_size 或 ARRAY_SIZE、MAP_SIZE。
- Hologres 文档中 ARRAY_LENGTH 的签名带维度参数,一维数组也要写成 ARRAY_LENGTH(arr, 1)。
SORT_ARRAY 数组排序
- Spark 有两个排序函数:sort_array 升序时把 NULL 放在开头,array_sort 把 NULL 放在末尾。从 MaxCompute 或 Hive 迁移时应使用 sort_array,结果才一致。
- 降序的写法不同:MaxCompute 和 Spark 传第二个参数,Flink 传 ascending_order,Doris 用 ARRAY_REVERSE_SORT,Hive 和 Hologres 的函数只能升序。
- Hologres V1.3.18 之前会把 TEXT 数组转成 INT8 再排序,字符串内容不是数字时结果可能不符合预期,使用前先确认实例版本。
SPLIT 字符串拆分
- MaxCompute、Hive 和 Spark 按正则处理分隔符。用 . 或 | 拆分时要写成 '\\.' 或 '\\|',否则会被当成正则元字符,结果出错。
- MaxCompute 默认去掉末尾的空字符串:SPLIT('a,b,c,,', ',') 返回 ["a","b","c"]。其他引擎的处理方式不一定相同,需要保留时传入 false。
- 只需要取某一段时,Hologres 的 SPLIT_PART 和 Flink 的 SPLIT_INDEX 更直接。注意 SPLIT_PART 的序号从 1 开始,SPLIT_INDEX 为负数时返回 NULL。
WM_CONCAT 分组拼接字符串
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY ...),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
ANY_VALUE 取组内任意值
- NULL 的处理不同:MaxCompute 和 Doris 会优先返回非 NULL 值,Spark 默认可能返回 NULL,需要传 true 才会跳过 NULL。
DAYOFWEEK 星期几
- Hologres 的 EXTRACT(DOW ...) 以周日为 0,直接替换 DAYOFWEEK 会让每天都差 1,周日从 1 变成 0。
- “星期几”的编号有三种:DAYOFWEEK 周日为 1;MaxCompute 和 Spark 的 WEEKDAY 周一为 0;Hologres 的 ISODOW 周一为 1、周日为 7。迁移时先确认原 SQL 用的是哪一种。
- 需要“周一为 1、周日为 7”时,可以写成 (DAYOFWEEK(d) + 5) % 7 + 1,在 Hologres 中直接用 EXTRACT(ISODOW FROM d)。
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。
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 在七个引擎中都可用。
SUBSTR 截取子串
- 起始位置写 0 是常见错误。MaxCompute 默认、StarRocks 和 Doris 都返回空字符串,不会报错,结果却全是空值,很难发现。MaxCompute 开启 Hive 兼容模式后又会按 1 处理,同一条 SQL 在不同模式下结果不同。
- Hologres 直接写 SUBSTR 可能报函数不存在,需要先创建 orafce 扩展,或改用标准的 SUBSTRING。
UNIX_TIMESTAMP 日期转时间戳
- 格式参数的写法不同:StarRocks 和 Doris 用 %Y-%m-%d %H:%i:%s,Hive、Spark 和 Flink 用 yyyy-MM-dd HH:mm:ss,MaxCompute 不支持格式参数。
WEEKOFYEAR 一年中的第几周
- Hologres 的 EXTRACT 返回 DOUBLE PRECISION,直接拼接字符串会得到 12.0 这类结果,需要先 CAST 成整数。
- MaxCompute 可以通过第二个参数改成周日开始,其他引擎的 WEEKOFYEAR 没有这个参数。
可以直接用的函数
下面 16 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。