首页 / 工具 / 迁移清单 / Spark SQL → Hive
Spark SQL 迁移到 Hive 的函数改写清单
从 Spark SQL 迁移到 Hive 时,在 Spark SQL 有对应写法的 44 个常用函数中,11 个需要改写。逐个列出两边写法和注意事项。
需要改写的函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Hive 迁移到 Spark SQL
需要改写的函数
| 函数 | Spark SQL 写法 | Hive 写法 | Hive 说明 |
|---|---|---|---|
| ANY_VALUE | any_value(expr[, isIgnoreNull]) | 需改写 max(col) | 函数手册中没有 ANY_VALUE,组内值都相同时用 max 或 min 代替。 |
| APPROX_COUNT_DISTINCT | approx_count_distinct(expr[, relativeSD]) | 需改写 COUNT(DISTINCT col) | 内置函数文档中没有近似去重函数,只能用精确的 COUNT(DISTINCT)。 |
| DATEADD | ts + INTERVAL n HOUR | 需改写 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。 |
| DAYOFWEEK | dayofweek(date) | 需改写 extract(dayofweek FROM ts) | 内置函数文档中没有 dayofweek 函数,Hive 2.2.0 起可以用 extract 取 dayofweek,文档示例中 2016-10-20(周四)返回 5,即周日为 1。 |
| DECODE | decode(expr, search, result [, search, result ] ... [, default]) | 需改写 CASE expr WHEN search THEN result ... ELSE default END | Hive 的 decode(binary bin, string charset) 是按字符集把二进制解码为字符串,不能做多值匹配,需要用 CASE 改写。 |
| FROM_JSON | from_json(jsonStr, schema[, options]) | 需改写 json_tuple(jsonStr, k1, k2, ...) | 内置函数中没有 FROM_JSON。一次取多个 key 用 json_tuple,它是 UDTF,要配合 LATERAL VIEW 使用;取单个值用 get_json_object。 |
| MAX_BY | max_by(x, y[, k]) | 需改写 ROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1 | 函数手册中没有 MAX_BY,用窗口函数取每组第一行。 |
| SPLIT_PART | split_part(str, delimiter, partNum) | 需改写 split(str, pat)[n - 1] | 内置函数中没有 SPLIT_PART。split 的第二个参数是正则表达式,返回数组,数组下标从 0 开始。 |
| TO_CHAR | to_char(expr, format) | 需改写 date_format(ts, 'yyyy-MM-dd HH:mm:ss') | 内置函数中没有 TO_CHAR。date_format 使用 Java 风格格式符。 |
| WM_CONCAT | string_agg(expr[, delimiter]) WITHIN GROUP (ORDER BY ...) | 需改写 concat_ws(',', collect_list(col)) | 函数手册中没有 WM_CONCAT,用 concat_ws 拼接 collect_list 的结果,顺序不固定。 |
迁移注意事项
ANY_VALUE 取组内任意值
- NULL 的处理不同:MaxCompute 和 Doris 会优先返回非 NULL 值,Spark 默认可能返回 NULL,需要传 true 才会跳过 NULL。
APPROX_COUNT_DISTINCT 近似去重计数
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
DATEADD 按单位加减日期
- Spark 3.4.0 起的 dateadd(d, 1) 表示加 1 天,参数个数和含义都与 MaxCompute 不同,不能直接照搬。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- 返回类型不同:MaxCompute 对 DATE 输入返回 DATE,Hologres 和 Spark 的 date_trunc 返回时间戳。结果用于关联 DATE 字段时要先转换。
- 周的起点:MaxCompute 的 week 默认从周一开始,Doris 和 Spark 文档的示例也截断到周一。按周汇总前确认业务定义的周起点。
- Hive 的 trunc 只能截断到月和年,按周、按季度汇总需要自己计算。
DAYOFWEEK 星期几
- “星期几”的编号有三种:DAYOFWEEK 周日为 1;MaxCompute 和 Spark 的 WEEKDAY 周一为 0;Hologres 的 ISODOW 周一为 1、周日为 7。迁移时先确认原 SQL 用的是哪一种。
- Hive 的内置函数文档没有 dayofweek,只能用 Hive 2.2.0 起提供的 extract(dayofweek FROM ...)。
DECODE 多值匹配
- Hive 和 Flink 也有 DECODE,但含义是字符集解码。把 MaxCompute 的多参数 DECODE 原样搬过去会报参数错误,必须改写成 CASE。
- Spark 3.2 之前只有字符集解码的 decode,多值匹配写法在旧版本中会报错。
SPLIT_PART 按分隔符取第 N 段
- 下标越界时结果不同:MaxCompute、StarRocks 和 Spark 返回空字符串,Hologres 和 Doris 返回 NULL。下游用 IS NULL 或 = '' 判断时,迁移后结果可能变化。
- Hive 的 split 按正则切分。分隔符是 .、| 这类正则特殊字符时,要写成 split(s, '\\.'),否则结果不对。
- Hive 的数组下标和 Flink 的 SPLIT_INDEX 都从 0 开始。从 SPLIT_PART 改写时要把下标减 1。
- 取最后一段时,StarRocks 和 Spark 可以直接传 -1。MaxCompute 要求下标大于 0,不能这样写。
TO_CHAR 日期转字符串
- MaxCompute 的 'yyyy-mm-dd' 原样搬到 Hive、Spark 或 Flink,mm 会被当成分钟,结果类似 2026-30-14,而且不会报错。Java 风格要写 'yyyy-MM-dd'。
可以直接用的函数
下面 33 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。
- ADD_MONTHS 按月加减
- ARRAY_CONTAINS 判断数组是否包含元素
- COALESCE 取第一个非空值
- COLLECT_LIST 聚合为数组
- COLLECT_SET 去重聚合为数组
- CONCAT 字符串拼接
- CONCAT_WS 按分隔符拼接
- DATE_ADD 日期加减
- DATE_FORMAT 日期格式化
- DATE_SUB 日期减天数
- DATEDIFF 日期差
- EXPLODE 数组展开为多行
- FROM_UNIXTIME 时间戳转日期
- GET_JSON_OBJECT 提取 JSON 字段
- GETDATE 获取当前时间
- IF 条件判断
- INSTR 查找子串位置
- LAST_DAY 当月最后一天
- LENGTH 字符串长度
- MONTHS_BETWEEN 相差月数
- NVL 空值替换
- PERCENTILE_APPROX 近似分位数
- REGEXP_EXTRACT 正则提取
- REGEXP_REPLACE 正则替换
- SIZE 数组和 Map 元素个数
- SORT_ARRAY 数组排序
- SPLIT 字符串拆分
- STR_TO_MAP 字符串转 Map
- SUBSTR 截取子串
- SUBSTRING_INDEX 按分隔符截取
- TO_DATE 字符串转日期
- UNIX_TIMESTAMP 日期转时间戳
- WEEKOFYEAR 一年中的第几周