![[AWS Glue]データカタログに作成されたパーティションをAWS CLIで削除してみた](https://devio2023-media.developers.io/wp-content/uploads/2019/04/aws-glue.png)
[AWS Glue]データカタログに作成されたパーティションをAWS CLIで削除してみた
この記事は公開されてから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スタックのテンプレートです。
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種類のパーティションパスのオブジェクトを作成します。
{"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で用意しておきます。
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
以上








