问题描述
公司同事使用 datax 同步 hive表(parquet格式) 到 starrocks。 但是同步成功之后,发现starrocks中的etl_update_time字段 比源表的 该字段早了8小时。 源表该字段为 timestamp类型,目标表的该字段为 datetime类型
问题分析
一听到早了8小时,大概率知道,应该是impala的时区问题导致的。 于是联想到 datax的限制:由于datax hdfsreader无法读取 parquet格式表, 于是使用了 rdbmsReader,利用impala jdbc去查询hive表的数据,然后将查询结果导入 starrocks。 这里就会出现问题,因为公司impala版本 有时区漂移问题,导致如果hive表 格式为parquet,字段为timestamp,那么impala读取出来的数据,默认使用的是UTC,结果会不正确,假设本地是中国时间,即CST时区,会慢8个小时。
问题验证
建立一张parquet格式的hive表
CREATE TABLE sync2startrocks2(
id int,
name string,
etl_update_time TIMESTAMP
)PARTITIONED BY (`dt` string)
STORED AS PARQUET
;
插入两条数据:
insert into table bd_sync.sync2startrocks2 partition(dt='2022-03-20') select 1, '1', current_timestamp();
insert into table bd_sync.sync2startrocks2 partition(dt='2022-03-20') select 2, '2', current_timestamp();
在hive查询刚插入的数据,确认时间没有问题
1 1 2022-03-21 15:24:38.747 2022-03-20
2 2 2022-03-21 15:24:58.068 2022-03-20
切换查询引擎为impala,查询该表中的数据
SELECT id,name,etl_update_time from bd_sync.sync2startrocks2
1 1 2022-03-21 07:24:38.747000000
2 2 2022-03-21 07:24:58.068000000
可以观察到, 目标端的etl_update_time字段明显比源端的该字段要慢8小时。
- 问题得到验证,确实是由于impala的时区问题导致。
解决办法
在拼写datax配置文件时,需要将impala的查询sql进行特殊处理,如下:
select id,name,from_utc_timestamp(`etl_update_time`,'Asia/Shanghai') from bd_sync.sync2startrocks2;
1 1 2022-03-21 15:24:38.747000000
2 2 2022-03-21 15:24:58.068000000
这样的话,相当于将查询出来的结果的时区转换一下,得到原来正确的时区数据。搞定
结论
- 如果带有timestamp字段的表由Impala生成无论是文本文件还是parquet文件时,无论是由Hive查询还是Impala,均不会有时区的问题。
- 由Hive生成的带有timestamp字段的表,如果是文本格式的,无论是由Hive查询还是Impala,均不会有时区的问题。
- 由Hive生成的带有timestamp字段的表,如果是parquet格式的,由Hive查询不会有时区的问题,由Impala查询时,默认使用的是UTC时区,结果会不正确,假设你本地是中国时间,即CST时区,会慢8个小时。
|