AWS - Redshift - 外部表读取 Parquet 文件中 timestamp 类型的数据

发布于:2025-02-23 ⋅ 阅读:(11) ⋅ 点赞:(0)

问题:

通过 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)