この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
AWS Glueでは、パーティション分割を行うことによりデータの整理や効率的なクエリ実行を行うことが可能です。
今回は、AWS GlueのデータカタログのパーティションをAWS CLIで更新してみました。
やってみた
環境準備
CloudFormationスタックをデプロイします。これによりyear
、month
、day
のパーティションキーを持ったデータカタログテーブルを作成します。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DevicesRawDataBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub devices-raw-data-${AWS::AccountId}-${AWS::Region}
DevicesDataAnalyticsGlueDatabase:
Type: AWS::Glue::Database
Properties:
CatalogId: !Ref AWS::AccountId
DatabaseInput:
Name: devices_data_analystics
DevicesRawDataGlueTable:
Type: AWS::Glue::Table
Properties:
CatalogId: !Ref AWS::AccountId
DatabaseName: !Ref DevicesDataAnalyticsGlueDatabase
TableInput:
Name: devices_raw_data
TableType: EXTERNAL_TABLE
Parameters:
has_encrypted_data: false
serialization.encoding: utf-8
EXTERNAL: true
StorageDescriptor:
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Columns:
- Name: device_id
Type: string
- Name: timestamp
Type: bigint
- Name: state
Type: boolean
InputFormat: org.apache.hadoop.mapred.TextInputFormat
Location: !Sub s3://${DevicesRawDataBucket}/raw-data
SerdeInfo:
Parameters:
paths: "device_id, timestamp, state"
SerializationLibrary: org.apache.hive.hcatalog.data.JsonSerDe
PartitionKeys:
- Name: year
Type: string
- Name: month
Type: string
- Name: day
Type: string
DevicesAthenaWorkGroup:
Type: AWS::Athena::WorkGroup
Properties:
Name: devices-athena-work-group
WorkGroupConfiguration:
ResultConfiguration:
OutputLocation: !Sub s3://${DevicesRawDataBucket}/athena-query-result
EnforceWorkGroupConfiguration: true
PublishCloudWatchMetricsEnabled: true
% aws cloudformation deploy \
--template-file template.yaml \
--stack-name devices-data-analytics-stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
以降のコマンド実行で使用する変数を定義します。
% AWS_REGION=ap-northeast-1
% ACCOUNT_ID=$(aws sts get-caller-identity | jq -r ".Account")
% RAW_DATA_BUCKET=s3://devices-raw-data-${ACCOUNT_ID}-${AWS_REGION}
% GLUE_DATABASE_NAME=devices_data_analystics
% GLUE_TABLE_NAME=devices_raw_data
パーティションとなるパスを持つデータをS3バケットに作成します。
raw-data.json
{"device_id": "3ff9c44a", "timestamp": 1609348014, "state": true}
% aws s3 cp raw-data.json \
${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=06/raw-data.json
この時点ではデータカタログにパーティションはまだ作成されていません。
% aws glue get-partitions \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${GLUE_TABLE_NAME}
{
"Partitions": []
}
athena start-query-execution
コマンドによる方法
athena start-query-execution
コマンドでMSCK REPAIR TABLE
クエリを実行する方法でパーティションを更新してみます。
% aws athena start-query-execution \
--query-string "MSCK REPAIR TABLE ${GLUE_TABLE_NAME}" \
--work-group devices-athena-work-group \
--query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
パーティション一覧を取得すると、パーティションが作成されていますね。
% aws glue get-partitions \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${GLUE_TABLE_NAME}
{
"Partitions": [
{
"Values": [
"2021",
"01",
"06"
],
"DatabaseName": "devices_data_analystics",
"TableName": "devices_raw_data",
"CreationTime": "2021-01-06T21:29:24+09:00",
"LastAccessTime": "1970-01-01T09:00:00+09:00",
"StorageDescriptor": {
"Columns": [
{
"Name": "device_id",
"Type": "string"
},
{
"Name": "timestamp",
"Type": "bigint"
},
{
"Name": "state",
"Type": "boolean"
}
],
"Location": "s3://devices-raw-data-XXXXXXXXXXXX-ap-northeast-1/raw-data/year=2021/month=01/day=06",
"InputFormat": "org.apache.hadoop.mapred.TextInputFormat",
"OutputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
"Compressed": false,
"NumberOfBuckets": 0,
"SerdeInfo": {
"SerializationLibrary": "org.apache.hive.hcatalog.data.JsonSerDe",
"Parameters": {
"paths": "device_id, timestamp, state"
}
},
"BucketColumns": [],
"SortColumns": [],
"Parameters": {},
"StoredAsSubDirectories": false
}
}
]
}
その他の方法
glue create-partition
やglue batch-create-partition
コマンドでもパーティションの作成は可能です。ただし前述の方法とは異なり、作成したいパーティションの仕様を明示的に指定する必要があります。
- create-partition — AWS CLI 1.18.209 Command Reference
- batch-create-partition — AWS CLI 1.18.209 Command Reference
オブジェクトが一つも作成されていない場合
S3バケットのデータロケーションにオブジェクトが一つも作成されていない場合、MSCK REPAIR TABLE
クエリは失敗します。
先程S3バケットに作成したオブジェクトを削除します。
% aws s3 rm \
${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=06/raw-data.json
athena start-query-execution
コマンドでパーティションを更新するクエリを実行します。
% aws athena start-query-execution \
--query-string "MSCK REPAIR TABLE ${GLUE_TABLE_NAME}" \
--work-group devices-athena-work-group \
--query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
{
"QueryExecutionId": "949737b5-2514-4dd2-abf6-c997d8f5143e"
}
クエリの実行結果を取得すると、Tables missing on filesystem:\tdevices_raw_data
というエラーとなっています。
% aws athena get-query-results \
--query-execution-id 949737b5-2514-4dd2-abf6-c997d8f5143e
{
"ResultSet": {
"Rows": [
{
"Data": [
{
"VarCharValue": "Tables missing on filesystem:\tdevices_raw_data"
}
]
}
],
"ResultSetMetadata": {
"ColumnInfo": []
}
},
"UpdateCount": null
そもそもオブジェクトをすべて削除する状況があまり無いですし、その状況になったとしてパーティション更新がエラーになったからと言ってすぐに困ることは無いですが、私はこの検証を行う際にバケットにデータを上げ忘れたままパーティション更新を行おうとして今回のエラーが出たため、「なんでテーブルが無いなんて言ってるんだ?」と少し混乱しました。
おわりに
AWS GlueのデータカタログのパーティションをAWS CLIで更新してみました。
Glueで構築したETLシステムにおいてはパーティション更新はクローラーやLambdaで行うことが多いと思いますが、これを応用すればGlueジョブの中でBoto3を使ってジョブ冒頭でパーティション更新させて構成を単純化させる、なんてこともできそうですね。
参考
- Demystifying the ways of creating partitions in Glue Catalog on partitioned S3 data for faster insights | by Subhash Burramsetty | Medium
- AWS Glueデータカタログへのテーブルの作成とAthenaの設定をCloudFormationでやってみた | Developers.IO
- get-query-results — AWS CLI 1.18.209 Command Reference
- rm — AWS CLI 1.18.209 Command Reference
以上