Tips

AWS Glue Crawlerの増分クロールでハマった落とし穴と対策

はじめに

データレイクを運用していると、AWS Glue Crawler による 増分クロール はコスト削減の切り札です。ところが設定を誤ると「新しいパーティションが作成されず Athena でクエリーできない」という落とし穴に遭遇します。この記事ではその原因と具体的な対処法を共有します。

AWS Glueとは何でしょうか?

GlueはS3などに置いたCSVやJSONファイルに対してデータベーススキーマ定義を作ってAthenaからクエリーできるようにする橋渡し的な役割を担っています。

簡単に用語を解説します。

データソース:S3のパスなどを指定してその中にあるファイルからデータ抽出する
スキーマ:データソースを元にしたデータベース定義
パーティション:データソースのデータに効率よくアクセスするための区切り。スキーマにパーティションの定義を持つ。新しいパーティションは明示的にデータベースに追加してあげないと検索できない。パーティションはS3だとディレクトリ別になっている。

Glue Crawlerとは

Glue Crawlerでデータソースを巡回して新しいディレクトリが出来ていたらパーティションを追加し、その中のファイルを元にスキーマを再定義したりすることが出来ます。
あたらしいディレクトリが出来た時、そのパーティションが追加されないと、Athenaからアクセスすることができません。一度追加されれば、そのディレクトリに新しくファイルが追加されても再クロールする必要はなく、Athenaから参照できます。
ディレクトリの中に読み込めるファイルがないとクロールしてもパーティションは追加されません。

Glue Crawlerの設定をどうするか

Glueの使用料金は高いです。Crawlerの実行時間と、巡回するデータ量によって課金されます。ですのでコストを考えたらなるべく少ない巡回数で、必要最小限の範囲をスキャンするのがコツです。

少ない巡回数にする

Crawlerの実行は、タイムスケジューラーと、トリガーが使えます。タイムスケジューラーは1日1回とか、毎時3分とか、19:00とかCron形式で指定できます。トリガーは、S3にファイルが上がったらとか、SQSなどが使えます。
または、Lambdaからキックすることも可能です。
目的やSLAに合わせて適切なタイミングで実行するようにします。

少ないスキャン量にする

クロールするたびに全データソースをスキャンしなおす必要がない場合、データソースの設定で、「Crawl new sub-folders only」にチェックをつけると、最後のスキャン以降に追加されたディレクトリのみをクロールします。(テーブルの追加がなく、スキーマも変わらない場合は、新しいディレクトリだけスキャンすればよいのでこの設定を選択します)
これが「増分クロール」です。
また、「Sample only a subset files」にチェックを入れ、スキャンするファイル数を「1」にすれば、追加されたディレクトリの1ファイルだけをスキャンしてくれます。全部のファイルをスキャンするよりデータ量が少なそうです。

そこで落とし穴にハマりました

前提:実データファイルが来る前にパーティション追加しておく運用をしていた

開発中のサービスでは、S3に新規ディレクトリが出来てファイルがアップされたら、すぐAthenaでクエリーする必要がありました。しかしクロールには何分もかかるため、すぐクエリー出来る状態にならない。そこで、あらかじめディレクトリを作っておき、空のjson({})ファイルをダミーで置いて定期的にスキャン実行し、本当のデータのjsonがアップされたらすぐにクエリーできるという仕組みにしていました。ダミーファイル名は先頭を「.」にして隠しファイルにしました。(隠しファイルはAthenaで無視されます。)
この時点では、データソースの設定は「Crawl all sub-folders」にしていました。

「Crawl new sub-folders only」に変更

しかしGlueの費用が高いので「Crawl new sub-folders only」に変更し、増分だけクロールすることにしました。
この設定で新しいディレクトリがきちんとパーティション追加されるかどうか気になったので、テストでディレクトリを作り、ダミーファイルとして空のjson({})をアップしました。そして試しに手動でクロールさせてそのディレクトリがパーティション追加されるかを確認しました。

するとパーティション追加されておりました。これでヨシ!

Athenaからデータが検索できないぞ

運用していくと、このクローラー設定の変更後に新しく追加されたディレクトリのパーティションが追加されなくて、Athenaからクエリーできないという事態が発生していました。

解説(なぜ新規ディレクトリがパーティション追加されなかったか)

新しいパーティションを追加するための増分クロールのスケジューリング

こちらを見ると、

クローラーは、初回実行時にデータソース全体を処理するフルクロールを実行し、完全なスキーマと既存のすべてのパーティションを AWS Glue Data Catalog に記録します。

最初のフルクロールの後のクロールは増分となり、クローラーは前回のクロール以降に導入された新しいパーティションのみを識別して追加します。

設定変更した直後のクロールは「フルクロール」になるようです。なので設定変更後、テストで新規ディレクトリを作り空のjsonをアップしたときは、全ディレクトリがスキャンされ、パーティション追加されたのでした。

二回目以降のクロールでは、

「同じスキーマ構造を持つファイルが存在する時にしかパーティション追加してくれない。」

つまりスキーマと異なる空のjsonがファイルとして存在したとて無視されてしまいます。パーティション無視されたディレクトリは、以降のクロールでは「新しいディレクトリではない」ためクロールされません。一度クロールされた後は、きちんとデータが入ったjsonが追加されようがもうパーティション化されないことになります。

対処

ダミーファイルを空ではなく、きちんとスキーマと同じ形式のダミーデータが入ったファイルにしました。データが入っていても、隠しファイルならばAthenaから無視されるのでクエリーに影響を与えません。これで、クロールさせたところ、ちゃんとパーティションが追加されました。

増分クロールするなら、ファイルの中身はスキーマ通りの構造にしましょう!

クローラーのテスト実行は2回以上行いましょう!

わたしたちはデータ分析とAIの専門家集団です。GRIと一緒に仕事をしませんか?

GRIへのお問い合わせはこちらから
reiko suzuki
SIerでのERPシステム開発職からWebデザイン会社のエンジニアに転職、出産後育休中の2021年にGRIに合流しました。子育てしながら在宅勤務で、Webサービスのシステム開発を行っています。AWSとWordPressが好きです。GRIの部活ではグルメ部とクリエイティ部に所属しています。
データ分析・AIの専門家集団 GRI