S3上のCSVファイルのスキーマが変更された際に、Athenaのクエリが変な動きをしているることがわかりました。
どうも、AWS GlueのCrawlerではCSVのスキーマの変更を上手く扱えないように見えました。
今までJSONやParquetなら大丈夫だったので、その辺り含めて検証した方法のメモです。
CSV/JSON/Parquetのファイルを生成
以下のようにPythonスクリプトで生成してみました。Google Colabなどで動かすとPC上の環境無しでも動かせます。
PC上で動かす場合は、pipでpyarrowのインストールが必要です。
import csv
import json
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
cases = [
("c0", {"a":1,"b":2,"c":3,"d":4}),
("c1", {"a":1,"b":2,"c":3,"c1":99,"d":4}),
("c2", {"a":1,"b":2,"c":3,"d":4,"d1":99}),
("c3", {"a":1,"b":2,"d":4,"d1":99}),
]
for c in cases:
case = c[0]
data = c[1]
# CSV出力
with open(f"{case}.csv","w") as f:
w = csv.DictWriter(f,fieldnames=list(data.keys()))
w.writeheader()
w.writerow(data)
# JSON出力
with open(f"{case}.json","w") as f:
json.dump(data,f)
# Parquet出力
pq.write_table(pa.Table.from_pandas(pd.DataFrame({k:pd.Series(v) for k,v in data.items()})),f"{case}.parquet")
ケース毎のCSV/JSON/Parquetファイルができました。
$ ls -1
c0.csv
c0.json
c0.parquet
c1.csv
c1.json
c1.parquet
c2.csv
c2.json
c2.parquet
c3.csv
c3.json
c3.parquet
S3にアップロードしてGlue Crawlerでクローリング
S3に以下のようにアップロードします。
BUCKET=bucket-name
aws s3 mb s3://${BUCKET}
for c in $(seq 0 3);
do
aws s3 cp c${c}.csv s3://${BUCKET}/csv/case=${c}/
aws s3 cp c${c}.json s3://${BUCKET}/json/case=${c}/
aws s3 cp c${c}.parquet s3://${BUCKET}/parquet/case=${c}/
done
以下のようにすると、csv/json/parquetというテーブルがcaseパーティション付きで作成されます。
Athenaで検索してみる
CSVとJSONとParquetをクエリしてみると、CSVだけ値がズレてしまっているのがわかります。
元々はこの挙動を確認するための手順でしたが、後々使えそうなので残しておきます。
SELECT * FROM "testdb"."csv" ORDER BY "case";
SELECT * FROM "testdb"."json" ORDER BY "case";
SELECT * FROM "testdb"."parquet" ORDER BY "case";