首页 / 工具 / 迁移清单 / Hive → Spark SQL
Hive 迁移到 Spark SQL 的函数改写清单
从 Hive 迁移到 Spark SQL 时,在 Hive 有对应写法的 44 个常用函数中,6 个需要改写,另有 5 个可以改用 Spark SQL 的原生函数。逐个列出两边写法和注意事项。
需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Spark SQL 迁移到 Hive
需要改写的函数
| 函数 | Hive 写法 | Spark SQL 写法 | Spark SQL 说明 |
|---|---|---|---|
| DATEADD | date_add(startdate, days) / add_months(startdate, n) | 需改写 ts + INTERVAL n HOUR | Spark 3.4.0 起有 dateadd(start_date, num_days),但只能加天数,没有单位参数。按小时、月等单位加减用 INTERVAL 字面量,按月也可以用 add_months。 |
| DATETRUNC | trunc(date, 'MM') | 需改写 date_trunc('MONTH', ts) | date_trunc 从 2.3.0 起提供,单位在前,返回 timestamp。只需要日期时可以用 trunc(date, fmt)。 |
| FROM_JSON | json_tuple(jsonStr, k1, k2, ...) | 支持 from_json(jsonStr, schema[, options]) | Spark 2.2.0 起提供。schema 用 DDL 字符串,例如 'a INT, b DOUBLE'。options 可以指定 timestampFormat 等解析选项。 |
| SPLIT_PART | split(str, pat)[n - 1] | 支持 split_part(str, delimiter, partNum) | Spark 3.3.0 起提供。下标从 1 开始,负数从末尾数。越界返回空字符串,partNum 为 0 时报错,分隔符为空字符串时不切分。 |
| TO_CHAR | date_format(ts, 'yyyy-MM-dd HH:mm:ss') | 支持 to_char(expr, format) | Spark 3.4.0 起提供。4.0 文档写明 expr 可以是日期时间,此时 format 使用 Java 风格格式符;更早的版本请按所用版本文档确认。也可以直接用 date_format。 |
| WM_CONCAT | concat_ws(',', collect_list(col)) | 需改写 string_agg(expr[, delimiter]) WITHIN GROUP (ORDER BY ...) | string_agg 和 listagg 从 Spark 4.0.0 起提供。更早的版本用 concat_ws(',', collect_list(expr))。 |
可以改用原生函数
下面的函数在 Hive 中只能用替代写法,Spark SQL 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。
| 函数 | Hive 写法 | Spark SQL 写法 | Spark SQL 说明 |
|---|---|---|---|
| ANY_VALUE | max(col) | 支持 any_value(expr[, isIgnoreNull]) | Spark 3.4.0 起提供,结果不确定。isIgnoreNull 为 true 时只返回非 NULL 值,默认可能返回 NULL。 |
| APPROX_COUNT_DISTINCT | COUNT(DISTINCT col) | 支持 approx_count_distinct(expr[, relativeSD]) | Spark 1.6.0 起提供,基于 HyperLogLog++。relativeSD 是允许的最大相对标准差。 |
| DAYOFWEEK | extract(dayofweek FROM ts) | 支持 dayofweek(date) | Spark 2.3.0 起提供,周日为 1,周六为 7。weekday(date) 则以周一为 0、周日为 6。 |
| DECODE | CASE expr WHEN search THEN result ... ELSE default END | 支持 decode(expr, search, result [, search, result ] ... [, default]) | 多值匹配写法 3.2.0 起支持。没有匹配且省略 default 时返回 NULL。同名的 decode(bin, charset) 用于按字符集解码。 |
| MAX_BY | ROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1 | 支持 max_by(x, y[, k]) | 传入 k 时返回 y 最大的前 k 个 x 组成的数组,k 最大 100,000。y 全为 NULL 时返回 NULL。 |
迁移注意事项
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 只能截断到月和年,按周、按季度汇总需要自己计算。
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'。
ANY_VALUE 取组内任意值
- NULL 的处理不同:MaxCompute 和 Doris 会优先返回非 NULL 值,Spark 默认可能返回 NULL,需要传 true 才会跳过 NULL。
APPROX_COUNT_DISTINCT 近似去重计数
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
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,多值匹配写法在旧版本中会报错。
可以直接用的函数
下面 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 一年中的第几周