首页 / 工具 / 迁移清单 / Hologres → Hive
Hologres 迁移到 Hive 的函数改写清单
从 Hologres 迁移到 Hive 时,在 Hologres 有对应写法的 43 个常用函数中,24 个需要改写(其中 1 个在 Hive 没有对应函数),另有 5 个可以改用 Hive 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Hive 迁移到 Hologres
需要改写的函数
| 函数 | Hologres 写法 | Hive 写法 | Hive 说明 |
|---|---|---|---|
| ADD_MONTHS | d + interval '1 month' | 支持 add_months(start_date, num_months[, output_date_format]) | Hive 1.1.0 起提供,返回 string。Hive 4.0.0 之前会忽略时间部分,4.0.0 起可以指定输出格式。 |
| APPROX_COUNT_DISTINCT | APPROX_COUNT_DISTINCT(column) | 需改写 COUNT(DISTINCT col) | 内置函数文档中没有近似去重函数,只能用精确的 COUNT(DISTINCT)。 |
| COLLECT_LIST | ARRAY_AGG(expression) | 支持 collect_list(col) | Hive 0.13.0 起提供,保留重复值。 |
| COLLECT_SET | ARRAY_AGG(DISTINCT expression) | 支持 collect_set(col) | 返回去重后的 array。 |
| DATE_ADD | DATEADD(d, num, 'day') | 支持 date_add(startdate, days) | Hive 2.1.0 之前返回 string,之后返回 date。 |
| DATE_FORMAT | TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') | 支持 date_format(ts, pattern) | Hive 1.2.0 起提供,输入可以是 date、timestamp 或 string。 |
| DATE_SUB | d - interval '1 day' | 支持 date_sub(startdate, days) | Hive 2.1.0 之前返回 string,之后返回 date。 |
| DATEADD | DATEADD(d, num, str) | 需改写 date_add(startdate, days) / add_months(startdate, n) | 内置函数中没有 DATEADD。按天加减用 date_add,按月加减用 add_months。 |
| DATETRUNC | DATE_TRUNC('month', ts) | 需改写 trunc(date, 'MM') | 函数手册中没有 date_trunc。trunc 只支持 MONTH、MON、MM 和 YEAR、YYYY、YY,返回 string。 |
| EXPLODE | UNNEST(anyarray) | 支持 explode(array | map) | UDTF,数组展开为一列 col,map 展开为 key 和 value 两列。需要元素位置时用 posexplode,位置从 0 开始。 |
| FROM_JSON | json_str::jsonb ->> 'key' | 需改写 json_tuple(jsonStr, k1, k2, ...) | 内置函数中没有 FROM_JSON。一次取多个 key 用 json_tuple,它是 UDTF,要配合 LATERAL VIEW 使用;取单个值用 get_json_object。 |
| FROM_UNIXTIME | TO_TIMESTAMP(seconds) | 支持 from_unixtime(unixtime[, pattern]) | 输入为距 1970-01-01 00:00:00 UTC 的秒数,返回 string。 |
| GETDATE | NOW() 或 CURRENT_TIMESTAMP | 别名 current_timestamp | Hive 1.2.0 起提供,返回查询开始时的时间戳,同一查询中各次调用结果相同。unix_timestamp() 无参写法从 2.0 起已废弃,文档建议改用 CURRENT_TIMESTAMP。 |
| INSTR | STRPOS(str, substr) | 支持 instr(str, substr) | 下标从 1 开始,找不到时返回 0,任一参数为 NULL 时返回 NULL。需要起始位置时用 locate(substr, str, pos)。 |
| MAX_BY | MAX_BY(x, y) | 需改写 ROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1 | 函数手册中没有 MAX_BY,用窗口函数取每组第一行。 |
| MAX_PT | MAX_PT('table_name') | 不支持 | 函数手册中没有 MAX_PT。改写为 WHERE pt = (SELECT MAX(pt) FROM t)。 |
| PERCENTILE_APPROX | APPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col) | 支持 percentile_approx(col, p[, B]) | 适用于浮点数在内的数值列,p 也可以传数组。B 默认 10000,列的不同值个数小于 B 时结果就是精确分位数。精确的 percentile 只支持整数列。 |
| REGEXP_EXTRACT | (REGEXP_MATCH(str, pattern))[n] | 支持 regexp_extract(subject, pattern, index) | 签名中 index 是必填参数,含义与 Java Matcher.group() 的下标相同。文档提醒 '\s' 匹配的是字母 s,匹配空白要写 '\\s'。 |
| SIZE | ARRAY_LENGTH(arr, 1) | 支持 size(array_or_map) | 同一个函数可以处理 ARRAY 和 MAP,返回 INT。 |
| SORT_ARRAY | ARRAY_SORT(anyarray) | 支持 sort_array(Array<T>) | Hive 0.9.0 起提供,只能升序。 |
| SPLIT | REGEXP_SPLIT_TO_ARRAY(str, pattern) | 支持 split(str, pat) | 返回 array,pat 是正则表达式。 |
| SPLIT_PART | SPLIT_PART(str, delimiter, num) | 需改写 split(str, pat)[n - 1] | 内置函数中没有 SPLIT_PART。split 的第二个参数是正则表达式,返回数组,数组下标从 0 开始。 |
| TO_CHAR | TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS') | 需改写 date_format(ts, 'yyyy-MM-dd HH:mm:ss') | 内置函数中没有 TO_CHAR。date_format 使用 Java 风格格式符。 |
| WM_CONCAT | STRING_AGG(expression, delimiter) | 需改写 concat_ws(',', collect_list(col)) | 函数手册中没有 WM_CONCAT,用 concat_ws 拼接 collect_list 的结果,顺序不固定。 |
可以改用原生函数
下面的函数在 Hologres 中只能用替代写法,Hive 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Hologres 写法 | Hive 写法 | Hive 说明 |
|---|---|---|---|
| MONTHS_BETWEEN | (EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b) | 支持 months_between(date1, date2) | Hive 1.2.0 起提供。同一天或都是月末时返回整数,否则按 31 天折算并考虑时间部分,结果保留 8 位小数。 |
| NVL | COALESCE(value, default_value) | 支持 NVL(value, default_value) | Hive 0.11 起提供。 |
| SUBSTR | SUBSTRING(str FROM start FOR len) | 支持 substr(str, start[, len]) | substr('foobar', 4) 返回 bar。手册没有说明负数和 0 的处理。 |
| UNIX_TIMESTAMP | EXTRACT(EPOCH FROM ts) | 支持 unix_timestamp(date[, pattern]) | 返回秒级 bigint。不带参数取当前时间的写法从 Hive 2.0 起已不推荐,建议用 CURRENT_TIMESTAMP。 |
| WEEKOFYEAR | EXTRACT(WEEK FROM ts) | 支持 weekofyear(string date) | 返回 INT,可以传入日期或时间戳字符串。 |
迁移注意事项
ADD_MONTHS 按月加减
- MaxCompute 返回字符串,Hive 4.0.0 之前也会丢掉时间部分。结果和 DATE 或 DATETIME 字段比较时,注意类型转换。
- Hologres 和 Flink 的月末行为文档没有写明,迁移涉及月末日期时建议用已知数据核对。
APPROX_COUNT_DISTINCT 近似去重计数
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
DATE_ADD 日期加减
- Hive 2.1.0 之前 date_add 返回字符串,老版本迁移来的 SQL 可能依赖了这个行为。
DATE_FORMAT 日期格式化
- Hologres 的 HH 默认是 12 小时制,下午的时间会少 12 小时,必须写 HH24。
DATE_SUB 日期减天数
- StarRocks 和 Doris 的 DATE_SUB 文档只列出 INTERVAL 写法。把 Hive 的 date_sub(d, 1) 搬到 StarRocks 时,改成 DATE_SUB(d, INTERVAL 1 DAY) 或 days_sub(d, 1)。
DATEADD 按单位加减日期
- MaxCompute 和 Hologres 中 mm 表示月,mi 表示分钟。把 DATEADD(d, 1, 'mm') 当成加 1 分钟,是迁移时最常见的错误。
- Hologres 的 DATEADD 默认只支持 1925~2282 年。9999-12-31 这类表示“永久有效”的日期需要单独处理。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
- Hive 的 trunc 只能截断到月和年,按周、按季度汇总需要自己计算。
EXPLODE 数组展开为多行
- 需要元素位置时,Hive 和 Spark 的 posexplode 位置从 0 开始,Flink 的 WITH ORDINALITY 从 1 开始,迁移时要调整下标。
FROM_UNIXTIME 时间戳转日期
- 返回类型不同:MaxCompute 返回 DATETIME,Hologres 的 TO_TIMESTAMP 返回 TIMESTAMPTZ,其他引擎返回字符串。拿结果做日期计算前,确认是否需要再转换类型。
GETDATE 获取当前时间
- 返回类型不同:MaxCompute、StarRocks 和 Doris 返回 DATETIME,Hologres 的 NOW 带时区(文档把不带时区的版本单独列为 LOCALTIMESTAMP),Flink 返回 TIMESTAMP_LTZ(3)。直接写入字符串或 DATETIME 字段时,格式可能变化。
- Hive 和 Spark 的 current_timestamp 可以不带括号,Doris 文档中的写法是 current_timestamp()。迁移时统一写 NOW() 更容易对齐。
INSTR 查找子串位置
- MaxCompute 的三参数和四参数写法,例如 INSTR(s, 'e', 3, 2),在 StarRocks、Doris、Hive、Spark 和 Flink 中都没有对应写法。只传起始位置时可以改成 LOCATE,取第 N 次出现时需要改写成多步计算。
- Hologres 的 INSTR 依赖 orafce 扩展。没有安装扩展时 SQL 会报函数不存在,改用 STRPOS 即可。
PERCENTILE_APPROX 近似分位数
- 第三个参数含义不同:MaxCompute 和 Hive 的 B、Spark 的 accuracy 都默认 10000;StarRocks 和 Doris 的 compression 只接受 2048~10000。从 Spark 迁移时,如果写了大于 10000 的 accuracy,要调整到这个范围内。
- Hologres 的 APPROX_PERCENTILE 需要 V3.1 及以上版本,而且只抽样 8,192 个元素。数据量很大时,尾部分位数(例如 P999)的误差可能偏大。
REGEXP_EXTRACT 正则提取
- 第三个参数是否必填不一样:MaxCompute、Spark 和 Flink 可以省略,默认取第 1 组;StarRocks、Doris 和 Hive 必须写上。迁移时统一写出分组下标最稳妥。
- Doris 默认用 RE2 语法,不支持 (?=...) 这类零宽断言。从 Hive 或 Spark 的 Java 正则迁移过来时,需要先确认是否用到这些写法。
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 按正则处理分隔符。用 . 或 | 拆分时要写成 '\\.' 或 '\\|',否则会被当成正则元字符,结果出错。
- 只需要取某一段时,Hologres 的 SPLIT_PART 和 Flink 的 SPLIT_INDEX 更直接。注意 SPLIT_PART 的序号从 1 开始,SPLIT_INDEX 为负数时返回 NULL。
SPLIT_PART 按分隔符取第 N 段
- 下标越界时结果不同:MaxCompute、StarRocks 和 Spark 返回空字符串,Hologres 和 Doris 返回 NULL。下游用 IS NULL 或 = '' 判断时,迁移后结果可能变化。
- Hive 的 split 按正则切分。分隔符是 .、| 这类正则特殊字符时,要写成 split(s, '\\.'),否则结果不对。
- Hive 的数组下标和 Flink 的 SPLIT_INDEX 都从 0 开始。从 SPLIT_PART 改写时要把下标减 1。
TO_CHAR 日期转字符串
- MaxCompute 的 'yyyy-mm-dd' 原样搬到 Hive、Spark 或 Flink,mm 会被当成分钟,结果类似 2026-30-14,而且不会报错。Java 风格要写 'yyyy-MM-dd'。
- Hologres 的 HH 默认是 12 小时制,下午 3 点会输出 03。需要 24 小时制时写 HH24。
MONTHS_BETWEEN 相差月数
- StarRocks 的 months_diff、Flink 的 TIMESTAMPDIFF 和 Hologres 的 EXTRACT 写法都只返回整数月,原 SQL 中依赖小数部分的计算(例如按 0.5 个月判断)需要重新设计。
- 时间部分的处理不同:Doris 只看日期,Hive 会把时间部分算进小数,Spark 在同一天或都是月末时忽略时间。同样的输入可能得到不同的小数。
- 舍入不同:Hive 和 Spark 默认保留 8 位小数,MaxCompute 返回完整的 DOUBLE,Doris 由 round_type 控制。和原结果做等值比较前,先统一 ROUND。
NVL 空值替换
- 迁移到 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 成整数。
可以直接用的函数
下面 14 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。