この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部の鈴木です。
Athenaのstruct型でテーブルのカラムを定義していて、読み込み元のファイル内で要素が増減していたとき、検索結果はどのような影響を受けるのか気になったので確認してみました。
結果としては、オブジェクトの要素が定義から増減していても検索は行うことができ、未定義の要素は検索結果には表示されず、テーブルには定義されているけれどファイルに存在しない要素はnull
になることが分かりました。
準備
読み込み用のテーブルの準備
読み込み用のテーブルを作成しておきました。
DDLは以下になります。データを置いておくバケット
とデータを置いておくパス
は必要なものに変えておきます。
CREATE EXTERNAL TABLE `struct_sample`(
`id` int,
`value` struct <
value1: int,
value2: int
>
)
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
's3://データを置いておくバケット/データを置いておくパス/'
読み込むファイルのフォーマットは、parquetで検証しました。整数値のid
カラムと、JSONが入っているvalue
カラムがある想定です。
value
カラムは挙動を確認したいstruct型にしておきました。
Glueデータカタログから確認すると、以下のようなスキーマになりました。
value
カラムの詳細はこのようになっています。
データの作成
JSON文字列を含むCSVを3種類作成し、parquetにしておきました。 CSVは以下の3つになります。
パターン1: 定義通りのJSONの文字列を含むもの
"id","value"
"1","{\"value1\": 11, \"value2\": 12}"
"2","{\"value1\": 21, \"value2\": 22}"
"3","{\"value1\": 31, \"value2\": 32}"
パターン2: 定義より1つ要素が多いJSONの文字列を含むもの
"id","value"
"4","{\"value1\": 41, \"value2\": 42, \"value3\": 43}"
"5","{\"value1\": 51, \"value2\": 52, \"value3\": 53}"
"6","{\"value1\": 61, \"value2\": 62, \"value3\": 63}"
パターン3: 定義より1つ要素が少ないJSONの文字列を含むもの
"id","value"
"7","{\"value1\": 71}"
"8","{\"value1\": 81}"
"9","{\"value1\": 91}"
以下のPythonスクリプトで、parquetに変換しておきました。
import json
import os
import pandas as pd
def convert_csv2parquet(filepath: str, pandas_dtype: dict):
""" 指定したファイルを読み込み、parquetに変換する。
"""
base_filename = os.path.splitext(os.path.basename(filepath))[0]
df = pd.read_csv(
filepath,
dtype=pandas_dtype,
escapechar = "\\"
)
df["value"] = df["value"].map(lambda x: json.loads(x))
df.to_parquet(f"./{base_filename}.parquet")
# 読み込み時の型を指定する
pandas_dtype = {
'id': int,
'value': str
}
# 変換を実行する
convert_csv2parquet("./sample1.csv", pandas_dtype)
convert_csv2parquet("./sample2.csv", pandas_dtype)
convert_csv2parquet("./sample3.csv", pandas_dtype)
作成したファイルはテーブルから参照できる箇所にアップロードしておきました。
やってみた
以下のクエリを実行して、まとめて値を参照してみました。
select
*
from struct_sample
order by id
結果は以下のようになりました。
オブジェクトの要素が定義から増減していても検索は行えていることが分かります。
テーブル定義内で未定義の要素value3
は結果として表示されていません。一方で、JSONにvalue2
が存在しないパターン3の場合、value2
はnull
になることが分かりました。
最後に
今回は、Athenaのstruct型でテーブルのカラムを定義していて、読み込み元で要素が変更されたとき、クエリ実行時にどのような挙動になるのかを確認してみました。
定義していないカラムは読めなかったり、存在しないカラムはnull
になったりはするものの、クエリ自体が失敗したりファイルが読み飛ばされたりしないことが分かったので安心しました。
参考になりましたら幸いです。