この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
AWS Glueではクローラーを使うことにより、指定したデータソースを解析して必要なパーティションやカラムなどのを持つGlueテーブルを自動作成し、継続的に更新させることができます。
一方で、手動で作成した既存のGlueテーブルを更新対象としたクローラーを作成することも可能です。
今回は、既存のGlueテーブルに対するクローラーをCloudFormationで作成してみました。
やってみた
まず最初に以降のコマンド実行で使用する変数を定義しておきます。
% 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
% RAW_DATA_GLUE_TABLE_NAME=devices_raw_data
% CRAWLER_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}
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
DevicesDataAnalyticsGlueCrawler:
Type: AWS::Glue::Crawler
Properties:
Name: devices-data-analytics
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/AWSGlueServiceRole-DefaultRole
Targets:
CatalogTargets:
- DatabaseName: !Ref DevicesDataAnalyticsGlueDatabase
Tables:
- !Ref DevicesRawDataGlueTable
SchemaChangePolicy:
DeleteBehavior: LOG
DevicesDataAnalyticsGlueCrawler
がクローラーのリソース定義となります。Properties.Targets.CatalogTargets
でクロール対象としたい既存のGlueテーブルを指定できます。
Properties.SchemaChangePolicy.DeleteBehavior
は、ドキュメントだと指定は必須となっていませんが、指定しない場合になぜか下記のエラーとなるのでLOG
を指定しています。
The SchemaChangePolicy for catalog targets can have only LOG DeleteBehavior value. Specify a value of LOG for the DeleteBehavior property.
クロール対象とするGlueテーブルDevicesRawDataGlueTable
のリソース定義では、Properties.TableInput.PartitionKeys
にてyear
、month
、day
の3つをパーティションキーとして指定しています。
スタックをデプロイします。
% aws cloudformation deploy \
--template-file template.yaml \
--stack-name devices-data-analytics-stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
データソースへのデータ作成
データソースのデータとして、Hive形式のパーティションパスを持つオブジェクトを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=13/raw-data.json
動作確認
クローラー実行前はGlueテーブルにパーティションは一つも作成されていません。
% aws glue get-partitions \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${RAW_DATA_GLUE_TABLE_NAME}
{
"Partitions": []
}
クローラーを実行します。
% aws glue start-crawler --name ${CRAWLER_NAME}
クローラーのステートがREADY
となれば実行は完了です。
% aws glue get-crawler --name ${CRAWLER_NAME} \
--query Crawler.State
"READY"
再度Glueテーブルのパーティションを取得してみると、アップロードしたオブジェクトで指定したパスのパーティションが作成されています。
% aws glue get-partitions \
--database-name ${GLUE_DATABASE_NAME} \
--table-name ${RAW_DATA_GLUE_TABLE_NAME} \
--query 'Partitions[0].Values'
[
"2021",
"01",
"13"
]
おわりに
既存のGlueテーブルに対するクローラーをCloudFormationで作成してみました。
当初クローラーで自動更新を行いたいGlueテーブルはクローラーで作成しないといけないと思い込んでいましたが、調査・検証してみると既存のGlueテーブルの更新にも対応していて良かったです。
参考
- Glueの使い方的な⑭(クローラー(Crawler)のSchemaChangePolicyその1) - Qiita
- [AWS Glue]データカタログのパーティションをAWS CLIで更新してみた | Developers.IO
- start-crawler — AWS CLI 1.18.213 Command Reference
- get-crawler — AWS CLI 1.18.213 Command Reference
以上