この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
AWS Glueでは、パーティション分割を行うことによりデータの整理や効率的なクエリ実行を行うことが可能です。
このパーティションですが、開発時の検証のために作成済みのものを削除したい時があります。
そこで今回は、AWS Glueのデータカタログに作成されたパーティションをAWS CLIで削除する方法を確認してみました。
やってみた
ここでは、「AWS CLIのglue
コマンド」と「Athenaでのクエリ実行」の2通りの方法について確認してみます。
最初に以降のコマンド実行で使用する変数を定義しておきます。
% 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
% ATHENA_WORK_GROUP_NAME=devices-data-analytics
環境構築
CloudFormationスタック
CloudFormationスタックのテンプレートです。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DevicesRawDataBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub devices-raw-data-${AWS::AccountId}-${AWS::Region}
DevicesDataAnalyticsAthenaWorkGroup:
Type: AWS::Athena::WorkGroup
Properties:
Name: devices-data-analytics
WorkGroupConfiguration:
ResultConfiguration:
OutputLocation: !Sub s3://${DevicesRawDataBucket}/query-result
EnforceWorkGroupConfiguration: true
PublishCloudWatchMetricsEnabled: true
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
リソース定義DevicesRawDataGlueTable
で、year
、month
、day
の3つのパーティションキーを持ったGlueテーブルを作成しています。
スタックをデプロイします。
% aws cloudformation deploy \
--template-file template.yaml \
--stack-name devices-data-analytics-stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
データの準備
データソースの場所となるS3バケットのパスに3種類のパーティションパスのオブジェクトを作成します。
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=13/raw-data.json
% aws s3 cp raw-data.json \
${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=14/raw-data.json
% aws s3 cp raw-data.json \
${RAW_DATA_BUCKET}/raw-data/year=2021/month=01/day=15/raw-data.json
共通スクリプトの用意
パーティション一括作成および一括取得の簡易化のため、共通スクリプトをMakefileで用意しておきます。
Makefile
export AWS_REGION=ap-northeast-1
export ACCOUNT_ID=$(shell aws sts get-caller-identity | jq -r ".Account")
export GLUE_DATABASE_NAME=devices_data_analystics
export GLUE_TABLE_NAME=devices_raw_data
export ATHENA_WORK_GROUP_NAME=devices-data-analytics
#パーティション一括作成
create-partitions:
aws athena start-query-execution \
--query-string "MSCK REPAIR TABLE $(GLUE_TABLE_NAME)" \
--work-group $(ATHENA_WORK_GROUP_NAME) \
--query-execution-context Database=$(GLUE_DATABASE_NAME),Catalog=AwsDataCatalog
#パーティション一括取得
get-partitions:
partitions=$$(aws glue get-partitions \
--database-name $(GLUE_DATABASE_NAME) \
--table-name $(GLUE_TABLE_NAME) \
--query Partitions\
);\
len=$$(echo $$partitions | jq length);\
for i in $$(seq 0 $$(($$len - 1)) );\
do echo $$partitions | jq ".[$$i].Values";\
done
AWS CLIのglue
コマンドによる方法
一つのパーティションの削除
パーティションを一つ削除する場合はdelete-partition
コマンドで可能です。
パーティションを一括作成した上で、year=2021,month=01,day=13
のパーティションを削除してみます。
% make create-partitions
% aws glue delete-partition \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${GLUE_TABLE_NAME} \
--partition-values 2021 01 13
パーティションを一括取得してみると、day=13
のパーティションだけ削除されて、day=14
およびday=15
のパーティションが残っていますね。
% make get-partitions
[
"2021",
"01",
"14"
]
[
"2021",
"01",
"15"
]
複数のパーティションの削除
複数のパーティションの一括削除はbatch-delete-partition
コマンドで可能です。
パーティションを一括作成し、batch-delete-partition
でday=13
およびday=14
を指定して実行してみます。({"Errors": [], ...}
のような実行結果が表示されますが無視してください)
% make create-partitions
% aws glue batch-delete-partition \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${GLUE_TABLE_NAME} \
--partitions-to-delete Values=2021,01,13 Values=2021,01,14
パーティションを一括取得してみると、day=13
およびday=14
のパーティションが削除されて、day=15
のパーティションだけ残っていますね。
% make get-partitions
[
"2021",
"01",
"15"
]
Athenaでのクエリ実行による方法
Athenaでのクエリ実行でパーティションを削除したい場合は、ALTER TABLE DROP PARTITION
クエリを使えば一つまたは複数の削除のいずれにも対応可能です。
一つのパーティションの削除
パーティションを一括作成して、ALTER TABLE DROP PARTITION
クエリでyear=2021,month=01,day=13
を指定して削除してみます。
% make create-partitions
% queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021', month='01', day='13')"
% aws athena start-query-execution \
--query-string ${queryString} \
--work-group ${ATHENA_WORK_GROUP_NAME} \
--query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
パーティションを一括取得してみると、day=13
のパーティションだけ削除されて、day=14
およびday=15
のパーティションが残っていますね。
% make get-partitions
[
"2021",
"01",
"14"
]
[
"2021",
"01",
"15"
]
複数のパーティションの削除
パーティションを一括作成して、ALTER TABLE DROP PARTITION
クエリでday=13
およびday=14
のパーティションを指定して削除してみます。
% make create-partitions
% queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021', month='01', day='13'), PARTITION (year='2021', month='01', day='14')"
% aws athena start-query-execution \
--query-string ${queryString} \
--work-group ${ATHENA_WORK_GROUP_NAME} \
--query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
パーティションを一括取得してみると、day=13
およびday=14
のパーティションが削除されて、day=15
のパーティションだけ残っていますね。
% make get-partitions
[
"2021",
"01",
"15"
]
すべてのパーティションを一括削除できないの?
できなさそうです。ただし近い方法としてAthenaによるALTER TABLE DROP PARTITION
クエリ実行であれば、一番カーディナリティが低いパーティションキーをすべて指定して削除する方法が良さそうでした。これなら今回のデータであれば(year='2021')
を指定するだけで一括削除できます。
% make create-partitions
% queryString="ALTER TABLE ${GLUE_TABLE_NAME} DROP PARTITION (year='2021')"
% aws athena start-query-execution \
--query-string ${queryString} \
--work-group ${ATHENA_WORK_GROUP_NAME} \
--query-execution-context Database=${GLUE_DATABASE_NAME},Catalog=AwsDataCatalog
また、出来そうで出来なかったクエリへの指定として、(year<>'')
や(year is not null)
、(year>'0')
、(year!='')
などがありました(実行してもエラーとなる)。下記によるとHive標準では使えるようですがAthenaでは使えないようです。
glue
コマンドの場合は、get-partitions
での取得結果をShellでゴニョゴニョしてbatch-delete-partition
に渡すしか無さそうです。下記が参考になります。
場合によってはGlueテーブルを作り直した方が手っ取り早いかも知れませんね。
おわりに
AWS Glueのデータカタログに作成されたパーティションをAWS CLIで削除する方法を確認してみました。
とりあえず今度から一括削除したい時はALTER TABLE DROP PARTITION
クエリでカーディナリティが低いパーティションキーを指定する方法を使いたいと思います。
参考
- [AWS Glue]データカタログのパーティションをAWS CLIで更新してみた | Developers.IO
- BatchDeletePartition - AWS Glue
- AWS CLI を使用した短縮構文の使用 - AWS Command Line Interface
- Makefile 動的な変数の使い分け - SIerだけど技術やりたいブログ
- /bashでjqを使ってJSONの配列をループさせる - Qiita
- コマンドライン上でのbashを1行で (for文/if文) - Qiita
- AWS CLI での文字列への引用符の使用 - AWS Command Line Interface
以上