Hive3的时间转换差8个小时
在Hive3中,由于时间戳默认使用UTC时区,转换过程少8小时。我们在hive中禁用了cast函数进行时间类型与数字类型的转化,如果有相关场景使用(例如从Hive2迁移Hive3),需要在业务侧进行改造,使用from_utc_timestamp 和 to_utc_timestamp函数替代。
改造前:
SELECT CAST(1597217764557 AS TIMESTAMP);

改造后:
select from_utc_timestamp(1597217764557,'GMT+8');

hive.groupby.skewindata 导致任务失败重试结果错误
问题现象:手动设置 hive.groupby.skewindata 参数为 true(这个默认是 false 的),就会在任务失败重试场景下,输出的结果少部分 Group By 相关的字段值。
解决方案:
【首选】设置 hive.groupby.skewindata 为 false,关闭 GroupBy 数据倾斜的优化,社区尚未修复此问题,可尝试使用 hive.map.aggr 解决数据倾斜问题。
【不推荐】如果非常需要 hive.groupby.skewindata 设置为 true 解决数据倾斜问题,设置 tez.am.task.max.failed.attempts = 0 让失败后不再进行 task 级别重试,避免出现成功但是数据出错情况。
分区表新增字段后,往旧分区插入数据,新字段值为NULL
问题现象:查询分区表,数据文件字段值不为空情况下,查询出来的字段值为 NULL。
原因:
- 这个表最近做了表结构变更,新加了一个字段。
- 之后又写了新的字段到旧的分区,但是旧分区在 COLUMNS_V2 表存储的字段列表并没有包含新的字段名(这是默认的Hive行为),
- 导致旧分区就算包含新字段的数据,也无法读出来。
解决方案: - 修复 COLUMNS_V2 表,对旧的 CD_ID 新增最近添加的字段。
SELECT * FROM COLUMNS_V2 WHERE CD_ID='1764367';
INSERT INTO COLUMNS_V2(CD_ID,COLUMN_NAME,TYPE_NAME,INTEGER_IDX) values (旧的CD_ID, xxx, xxx, 和新分区INTEGER_IDX一致);
- 如果想要新增字段对所有历史分区有效,那应该在 ALTER TABLE 时使用 CASCADE 关键字。
ALTER TABLE dbname.table_name ADD columns (column1 string,column2 string) CASCADE;
提示 Multiple partitions for one merge mapper
如果表存储格式为ORC。并且由于小文件问题hive.merge.tezfiles改成了true进行小文件输出合并,这里是hive的bug。
set hive.merge.tezfiles=false;
drop table异常提示You might need to increase max_locks_per_transaction.)FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask success
查看 metastore日志关键字:“Can not delete hdfs path”
解决:drop table 执行时,在一个事务里需要删除partitions的元数据,分区太多的话,会占用比较多的shared memory建议先TRUNCATE TABLE清空表数据,再删除表。
读取Snappy文件出现OOM
原因分析:LogService等服务写入的标准Snappy文件和Hadoop生态的Snappy文件格式不同,EMR默认处理的是Hadoop修改过的Snappy格式,处理标准格式时会报错OutOfMemoryError。
解决方法:对Hive作业配置如下参数。
set io.compression.codec.snappy.native=true;
Hive和Spark时区不一致导致结果不一致
异常现象:Hive的from_unixtime时区固定为UTC,而Spark使用的是本地时区,如果两者的时区不一致会导致结果不一致。
解决方法:修改Spark时区为UTC,在Spark SQL里面插入如下代码:
set spark.sql.session.timeZone=UTC;
或者修改Spark配置文件,添加新的配置:
spark.sql.session.timeZone=UTC