當我執行 AWS Glue 作業來處理儲存在 Amazon Simple Storage Service (Amazon S3) 中的 Parquet 或 ORC 檔案時,收到「無法推斷結構描述」錯誤。
簡短描述
Parquet 或 ORC 檔案必須遵循 Hive 樣式的 key=value 分區路徑格式。如果檔案改用階層路徑結構,則 AWS Glue 無法理解該結構描述並會失敗。
例如,如果您的 AWS Glue 作業處理來自 s3://s3-bucket/parquet-data/ 的檔案,則這些檔案必須使用下列分割格式:
s3://s3-bucket/parquet-data/year=2018/month=10/day=10/file1.parquet
如果檔案使用下列非分割格式,則 AWS Glue 作業將會失敗:
s3://s3-bucket/parquet-data/year/month/day/file1.parquet
解決方法
若要解決 AWS Glue 中的「無法推斷結構描述」錯誤,請根據您的使用案例使用下列其中一種方法。
重新架構您的資料
將檔案複製到新的 S3 儲存貯體,並使用 Hive 樣式的分割路徑。然後,執行該作業。
用星號替換分區欄名稱
如果您無法重新架構資料,請直接從 Amazon S3 建立 DynamicFrame。使用星號 (*) 替換分區欄名稱。AWS Glue 僅包含 DynamicFrame 中的資料,不包含分區欄。
例如,如果您將檔案儲存在檔案路徑為 s3://s3-bucket/parquet-data/year/month/day/files.parquet 的 S3 儲存貯體中,請使用下列 DynamicFrame:
dynamic_frame0 = glueContext.create_dynamic_frame_from_options(
's3',
connection_options={'paths': ['s3://s3-bucket/parquet-data/*/*/*']},
format='parquet',
transformation_ctx='dynamic_frame0'
)
使用對應類別轉換來新增分區欄
若要將分區欄包含在 DynamicFrame 中,請將資料讀入 DataFrame,並為 Amazon S3 檔案路徑新增一欄。然後,套用對應類別轉換。
程式碼範例:
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.dynamicframe import DynamicFrame
from pyspark.sql.functions import input_file_name
args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
df = spark.read.parquet("s3://s3-bucket/parquet-data/*/*/*")
modified_df = df.withColumn('partitions_column', input_file_name())
dyf_0 = DynamicFrame.fromDF(modified_df, glueContext, "dyf_0")
def modify_col(x):
if x['partitions_column']:
new_columns = x['partitions_column'].split('/')
x['year'], x['month'], x['day'] = new_columns[4], new_columns[5], new_columns[6]
del x['partitions_column']
return x
modified_dyf = Map.apply(dyf_0, f=modify_col)
datasink2 = glueContext.write_dynamic_frame.from_options(
frame=modified_dyf,
connection_type="s3",
connection_options={
"path": "s3://my-output-bucket/output/",
"partitionKeys": ["year", "month", "day"]
},
format="parquet",
transformation_ctx="datasink2"
)
**注意:**將範例 S3 路徑替換為您的 S3 路徑,並根據您的使用案例自訂分區欄。
解析不存在的檔案或首碼
如果路徑中沒有檔案,請檢查您是否刪除或封存了檔案。如果檔案使用不同的首碼,請更新 AWS Glue 指令碼中的 connection_options 參數,以指向正確的路徑。此外,請檢查目錄表是否參考了缺失或過時的 S3 位置。如果資料表指出檔案缺失,則作業會失敗,因為沒有資料可供處理。
解決使用作業書籤參數的作業掃描舊檔案時發生的問題
當您使用作業書籤時,AWS Glue 會追蹤先前處理過的檔案,並跳過時間戳記較舊的檔案。如果作業找不到符合條件的新檔案,則作業會失敗,因為沒有資料可處理。
若要解決此問題,請執行下列動作:
- 確認檔案修改的時間戳記在預期範圍內。
- 關閉書籤以重新處理所有檔案。
- 重新命名或更新檔案,使其具有較新的最後修改時間戳記,讓 AWS Glue 將其識別為新檔案,並在下次執行時納入處理。
相關資訊
在 AWS Glue 中管理 ETL 輸出的分區