AWS - Redshift - 外部表读取 Parquet 文件中 timestamp 类型的数据
问题:
通过 Redshift Spectrum 功能可以读取 S3 中的文件,当读取 Parquet 文件时,如果列格式设置为 timestamp, 通过 psql 客户端读取会出现以下错误:
testdb=# select * from myspectrum_schema_0219.test_ns;
ERROR: Assert
DETAIL:
-----------------------------------------------
error: Assert
code: 1000
context: status == 0 - timestamp: '-3784992261051417264'
query: 15121995
location: cg_util.cpp:705
process: padbmaster [pid=1073963104]
-----------------------------------------------
通过 Query Editor V2 读取,则显示错误的时间格式:
以下是 CSV 文件,以及通过 python 读取 Parquet 文件的内容:
CSV:
$ more data3.csv
saletime
2024-01-01 01:01:01.000000
2025-01-01 01:01:01.000000
2025-01-02 02:01:01.000000
2025-01-03 03:01:01.000000
2025-01-04 04:01:01.000000
2025-01-04 05:01:01.000000
Parquet:
>>> import pandas as pd
>>> import pyarrow.parquet as pq
>>> parquet_file = 'data3_ns.parquet'
>>> df_read = pd.read_parquet(parquet_file)
>>> print(df_read)
saletime
0 2024-01-01 01:01:01
1 2025-01-01 01:01:01
2 2025-01-02 02:01:01
3 2025-01-03 03:01:01
4 2025-01-04 04:01:01
5 2025-01-04 05:01:01
原因:
Redshift 中的时间类型支持到 us,也就是 微妙,而 Parquet 文件 timestamp 格式支持的类型为 ns,所以对于时间格式是无法读取,或读取错误。
解决:
在 Parquet 文件设置时间类型时,对值做设置,datetime64[us],以匹配 Redshift 的时间精度。
以下为CSV生成 Parquet 的代码:
import pandas as pd
import pyarrow.parquet as pq
# 读取 CSV 文件
csv_file = 'data3.csv'
df = pd.read_csv(csv_file)
# 假设 CSV 文件中有一个时间列 'timestamp',将其转换为微秒精度
df['saletime'] = pd.to_datetime(df['saletime']).astype('datetime64[us]')
# 将 DataFrame 保存为 Parquet 文件
parquet_file = 'data3_us.parquet'
df.to_parquet(parquet_file, engine='pyarrow')
# 读取 Parquet 文件以验证
df_read = pd.read_parquet(parquet_file)
print(df_read)
saletime
0 2024-01-01 01:01:01
1 2025-01-01 01:01:01
2 2025-01-02 02:01:01
3 2025-01-03 03:01:01
4 2025-01-04 04:01:01
5 2025-01-04 05:01:01
之后创建外部表进行查询,就可以成功匹配到正确的格式。
testdb=# CREATE EXTERNAL TABLE myspectrum_schema_0219.test_us(saletime timestamp)
testdb-# STORED AS parquet
testdb-# LOCATION 's3://XXX/redshiftspectrum/t_0220_p/t_0220_p_us/';
CREATE EXTERNAL TABLE
testdb=# select * from myspectrum_schema_0219.test_us;
saletime
---------------------
2024-01-01 01:01:01
2025-01-01 01:01:01
2025-01-02 02:01:01
2025-01-03 03:01:01
2025-01-04 04:01:01
2025-01-04 05:01:01
(6 rows)