はじめに
S3 に置かれているのはファイルです。Amazon Athena はそのファイルに対して SQL を実行できるサービスで、SELECT を書けば、結果が表として返ってきます。
ファイルの集まりをテーブルとして扱えるのは、2 つのものが組み合わさっているからです。S3 に置かれたデータの実体と、それをテーブルとして定義した AWS Glue データカタログです。
この記事では、その 2 つをそれぞれ解説します。S3 に置くファイルは、Parquet 形式を例にします。
用語整理
この記事に出てくる用語をまとめます。
| 用語 | 概要 |
|---|---|
| Amazon S3 | ファイル置き場。保存の単位はオブジェクト(ファイルと、それを説明するメタデータ) |
| Apache Parquet | 列指向のデータファイル形式 |
| AWS Glue データカタログ | テーブルの定義を保管しておく場所 |
| Amazon Athena | 標準 SQL で S3 のデータを分析するクエリサービス |
この記事では、EC サイトの注文ログを Athena で集計する、次の構成を例に説明します。
- 注文ログが Parquet 形式のファイルとして
s3://example-analytics/orders/に置かれている - Glue データカタログに
ordersというテーブルが定義され、そのLOCATIONが上の S3 のパスを指している - Athena は、カタログのテーブル定義を使って S3 のファイルを読み、SQL の結果を返す
Parquet とは
行で並べるか、列で並べるか
Apache Parquet は、オープンソースの「列指向(column-oriented)」のデータファイル形式です。効率的なデータの保存と取得のために設計されています。
たとえば注文ログに order_id / ordered_at / total_price の 3 列があるとします。
- CSV:列名を書いたヘッダー行に続けて、1 行分の値をカンマ区切りで並べる
- Parquet:同じ列の値をまとめて並べる
Parquet は実際にはバイナリなので、図は並び方だけを表したものです。
列指向フォーマットが Athena に適しているのは、次の 3 点です。
- データが小さくなる:列のデータ型に合わせた圧縮アルゴリズムが選ばれる。S3 の保存容量が減り、クエリ処理のときに読み書きするデータ量も減る
-
要らない部分を飛ばせる:データのまとまりごとに最大値・最小値などの統計を持つため、
WHERE total_price > 10000に合う値が無いまとまりは読まずに飛ばせる(述語プッシュダウン) - 手分けして読める:Athena が 1 つのファイルの読み取りを分担して、同時に読み進められる
圧縮されたデータへのクエリは速いうえに、Athena は解凍前のバイト数に対して課金するため、費用も抑えられます。
Parquet ファイルは「自分の設計図」を持っている
Parquet ファイルは、自分自身の構造の説明(メタデータ)を、ファイルの中に持っています。
ファイル全体は、次のような構造になっています。
先頭と末尾に PAR1 という 4 バイトの目印があり、その間に行グループ(row group)が並び、その後ろにファイルメタデータが置かれます。
行グループは、テーブルを何行かごとに区切ったものです。その各行グループの中で、列ごとにデータがまとまっています(column chunk)。
ファイルメタデータには、このファイルのスキーマ(すべての列の名前と型)、行数、そして各 column chunk がファイルのどこにあるかが記録されています。
Parquet を読むソフトウェアは、まずここを読んで、必要な column chunk の位置を知ります。メタデータがデータの後に書かれるのは、ファイルを 1 回書き通すだけで済むようにするためです。
Glue データカタログとは
なぜカタログが必要なのか
この記事の設定では、注文ログのファイルが S3 の orders/ フォルダに置かれ、Glue データカタログに orders テーブルが定義されています。フォルダの中のファイルは、バッチが動くたびに増えていき、数百個になることもあります。
この状態で Athena が SELECT ... FROM orders を処理するには、次の情報が必要です。
-
ordersという名前のテーブルは、S3 のどこを指しているのか - そのテーブルはどんな列を持ち、それぞれどんな型なのか
- ファイルはどの形式で書かれていて、どう解釈すればよいのか
このうち列と型は、Parquet ファイル自身もメタデータとして持っています。ただしそれは、そのファイル 1 つについての説明です。ファイルの中に、どのテーブルに属するかという情報はありません。
テーブル 1 つにつき 1 セットの定義が、ファイルの外側に必要です。その置き場所が Glue データカタログです。
S3 のファイル群と、カタログのテーブル定義の2つが揃って、SQL から見える orders テーブルになります。
カタログには何が入っているのか
Glue データカタログは、テーブルの定義を保管しておく場所です。データがどこにあるか、どんな列を持つか、といった情報の索引として機能します。テーブルは、データベースごとに整理されて格納されます。
Athena で CREATE TABLE を実行すると、そのテーブルの定義は Glue データカタログに登録されます。
Glue のテーブル定義のうち、この記事に関わるのは次の情報です。
- テーブル名とデータベース名:SQL から呼ぶときの名前
-
LOCATION:S3 のどのフォルダを指すか - 列のリスト:列名と型
- 形式と SerDe:ファイルがどの形式で書かれているか。SerDe は、その形式のデータを Athena が扱えるようにする仕組みです
いつ使われるのか
Athena は、テーブルを作った時点ではなく、データを読むときにカタログの定義を当てはめます。この方式をスキーマオンリード(schema-on-read)と呼びます。
カタログは、データが流れる経路の中にはありません。データはバッチから S3 へ書き込まれ、Athena が読み、その結果を BI ツールなどが利用します。カタログは、その外側から Athena に参照されます。
読むときに定義を当てはめる、ということは、次の 2 つを意味します。
1. カタログに定義されていない列は、Athena からは存在しない
S3 のファイルにその列が書き込まれていても、カタログに無ければ SQL からは参照できません。
2. カタログを書き換えても、S3 のデータは変わらない
スキーマの更新によって、基盤となるデータが変更されたり書き直されたりすることはありません。
まとめ
- Parquet は、列ごとにデータを並べるバイナリのファイル形式です。必要な列だけ読めるので、読み書きするデータ量を減らせます
- Glue データカタログには、テーブルの定義が入っています。どこにデータがあるか、どんな列を持つか、という情報です
- カタログにはテーブルの定義が、S3 にはデータの実体があります。両方が揃って初めて Athena で読めます
- Athena はスキーマオンリードで、読むときにカタログの定義を当てはめます。カタログを書き換えても、S3 のデータは変わりません
Athena で SQL を実行するには、カタログのテーブル定義と、その定義が指す S3 のファイルの両方が必要です。
用語補足
| 用語 | 意味 |
|---|---|
| 列指向(column-oriented) | 行単位ではなく列単位でデータを並べる保存方式。必要な列だけ読める |
| メタデータ | データそのものではなく、データの構造や所在を説明する情報 |
| スキーマ | 列名や型といった、表の構造の定義 |
| スキーマオンリード | テーブル作成時ではなく、データを読むときに定義を当てはめる方式 |
| 行グループ(row group) | Parquet ファイルの中で、テーブルを何行かごとに区切ったもの |
| column chunk | 1 つの行グループの中で、1 列分のデータがまとまった部分 |
| SerDe | Serializer/Deserializer。バイト列と行・列を相互変換する部品 |
| LOCATION | テーブルのファイルが置かれている S3 のフォルダ |
| 述語プッシュダウン | 統計を使って、読む必要のないデータのまとまりを読み飛ばす仕組み |
参考



