📚

【AWS 奮闘記】AWS Athena について 1

に公開

はじめに

AWS 認定 ソリューションアーキテクト – プロフェッショナルの資格取得を目指して勉強中です。
今回は AWS Athena のハンズオンを実施しました。
その過程で分かった AWS Athena の内容、経験を簡単にまとめました。

ハンズオンは Claude Code で作成したものです。

AWS Athena とは

AWS Athena とは、簡単に言うと「さまざまなデータソースをまとめて、単一の SQL で問い合わせできるサービス」です。
SQL で S3、RDS など複数のデータソースを横断して問い合わせできます。
複数データソースからのデータを結合して分析する際などに使用できるかなと思います。

実際にクエリしてみる

Athena のクエリエディタ画面です。右側のエディタにクエリを直接入力してハンズオンを進めました。
まずは、AWS S3 に保存されたデータを SQL で検索してみました。

Athenaクエリエディタ
AWS Athena クエリエディタ

クエリ結果保存先の設定

Athena のクエリ結果は S3 に保存されるため、結果の保存先(S3 パス)を設定する必要があります。
Athenaクエリ結果保存設定
AWS Athena クエリ結果保存先設定

データソースとなる CSV ファイルを S3 に格納

事前にデータソースとなる CSV ファイルを S3 に格納しておきます。
Athena でクエリを実行すると、この CSV ファイルが読み込まれます。
今回は athena-sample-data-[あなたのバケット名]/csv-data/ に、以下の CSV ファイルを 2 つ格納しました。

employees.csv
employee_id,name,department,salary,hire_date,city
1,山田太郎,Engineering,75000,2020-01-15,Tokyo
2,佐藤花子,Marketing,65000,2019-03-20,Osaka
3,田中次郎,Engineering,80000,2021-06-10,Tokyo
4,鈴木美咲,Sales,60000,2020-11-05,Nagoya
5,高橋健一,Engineering,85000,2018-08-12,Tokyo
6,渡辺あい,Marketing,70000,2021-02-28,Osaka
7,伊藤大輔,Sales,58000,2022-01-10,Fukuoka
8,中村由美,Engineering,82000,2019-09-15,Tokyo
9,小林直樹,Marketing,67000,2020-07-22,Osaka
10,加藤真理,Sales,62000,2021-11-18,Nagoya
sales_2023.csv
sale_id,product_id,employee_id,amount,sale_date,region
1,101,4,1200,2023-01-05,Kanto
2,102,7,800,2023-01-06,Kyushu
3,103,10,1500,2023-01-07,Chubu
4,101,4,950,2023-01-10,Kanto
5,104,7,2200,2023-01-12,Kyushu
6,102,10,1100,2023-01-15,Chubu
7,105,4,1800,2023-01-18,Kanto
8,103,7,1350,2023-01-20,Kyushu
9,101,10,1000,2023-01-22,Chubu
10,106,4,2500,2023-01-25,Kanto

Athena データベースの作成

まず、以下のクエリを実行してデータベースを作成しました。
この LOCATION は、テーブル作成時の既定の保存先として使用されます。(AWS のドキュメントによると...)

CREATE DATABASE IF NOT EXISTS company_db
    COMMENT 'Company sample database for Athena learning'
    LOCATION 's3://athena-sample-data-[あなたのバケット名]/databases/company_db/';

クエリは通常のSQLクエリとは違い、Athena用に拡張されているようです。

次に、以下のクエリで employees テーブルを作成しました。
これで、LOCATION で指定した S3 パスにある CSV ファイルが employees テーブルのデータとして参照されます。

CREATE EXTERNAL TABLE employees (
        employee_id int,
        name string,
        department string,
        salary bigint,
        hire_date date,
        city string
    )
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
    WITH SERDEPROPERTIES (
        'field.delim' = ',',
        'skip.header.line.count' = '1'
    )
    STORED AS TEXTFILE
    LOCATION 's3://athena-sample-data-[あなたのバケット名]/csv-data/'
    TBLPROPERTIES (
        'projection.enabled' = 'false',
        'classification' = 'csv'
    );
クエリの解説

ROW FORMAT SERDE部分

ここで、ファイルのパースに使用する Serialize/Deserialize のライブラリを指定します。
SERDE は、SERializer/DEserializer の略だと思います。

ここでは、org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDeが指定されています。
これは CSV 用の SERDE ライブラリです。

WITH SERDEPROPERTIES部分

WITH SERDEPROPERTIESは、SERDE のプロパティを指定する部分です。
ここでは、field.delimskip.header.line.countが指定されています。

  • field.delim:CSV ファイルの区切り文字を指定。
  • skip.header.line.count:CSV ファイルのヘッダーをスキップする行数を指定。

このあたりは AWS のドキュメントに直接の記載がなく、プロパティは SERDE ライブラリの定義を確認しました。
筆者は Apache Hive のソースでようやく見つけました...(Claude に聞かなかったら、もっと時間がかかっていました...)

STORED AS TEXTFILE部分

ここはテーブルデータ用のファイルフォーマット指定です。
TEXTFILEと書いてあるのでテキストファイルでテーブルデータが保存されます。
INSERT などの書き込み時に、この形式で保存されます。SELECT は書き込みを行わず、結果はクエリ結果保存先に出力されます。
TEXTFILE 以外にも指定できるフォーマットが存在し、クエリ効率の高い形式もあります。

LOCATION部分

ソースとなるデータファイルが保存されているS3のパスです。
この部分で指定した場所のデータが初期のテーブルデータとして読み込まれます。

TBLPROPERTIES部分

テーブルのメタデータを指定する部分です。
projection.enabledはパーティション関連の設定です。(パーティションについては別記事にします)
classificationはテーブルの種別を指定します。(ETL job用)

今回は Athena 初見だったため、Claude Code が生成したハンズオンをそのまま実施しました。少々冗長な設定が含まれているかもしれません。

画面のクエリエディタから SELECT クエリを発行

作成したデータベースを指定し、employees テーブルに対して SELECT クエリを発行しました。
Athenaクエリエディタ上のSELECTクエリ

結果を確認

このように、クエリエディタ下部に結果が表示されます(S3 のクエリ結果保存先にも保存されます)。
Athenaクエリ結果
結果を見てみると、なんかちぐはぐですよね...
これも学びだったので、この後紹介します。

ちなみに、INSERTした場合は、CREATE TABLE の LOCATION で指定した場所にデータファイルが作成されました(元データの CSV ファイルは更新されません)。
UPDATE は CSV テーブルではできません(Apache Iceberg テーブル形式でのみ可能だそうです。Apache Iceberg ってなんだろう🤔 後で調べておきます)

CREATE TABLE を実行すると、テーブルのメタデータ(テーブル情報)は AWS Glue データカタログに格納されます。
実際のデータは S3 から都度、スキャンして読み込まれるようです。
Athena クエリのパフォーマンス面では、S3 上のデータが読み込み効率の高い形式で保存されていることが重要です。

Athena のクエリ結果がちぐはぐな件

なぜこのように表示されるのか疑問に思い、四苦八苦しました...
Athenaクエリ結果

結論として、同じ場所に異なる 2 つの CSV ファイルを置いてしまったことが原因でした。
今回は、athena-sample-data-[あなたのバケット名]/csv-data/ に、以下の CSV ファイルを 2 つ格納していました。

employees.csv
employee_id,name,department,salary,hire_date,city
1,山田太郎,Engineering,75000,2020-01-15,Tokyo
2,佐藤花子,Marketing,65000,2019-03-20,Osaka
3,田中次郎,Engineering,80000,2021-06-10,Tokyo
4,鈴木美咲,Sales,60000,2020-11-05,Nagoya
5,高橋健一,Engineering,85000,2018-08-12,Tokyo
6,渡辺あい,Marketing,70000,2021-02-28,Osaka
7,伊藤大輔,Sales,58000,2022-01-10,Fukuoka
8,中村由美,Engineering,82000,2019-09-15,Tokyo
9,小林直樹,Marketing,67000,2020-07-22,Osaka
10,加藤真理,Sales,62000,2021-11-18,Nagoya
sales_2023.csv
sale_id,product_id,employee_id,amount,sale_date,region
1,101,4,1200,2023-01-05,Kanto
2,102,7,800,2023-01-06,Kyushu
3,103,10,1500,2023-01-07,Chubu
4,101,4,950,2023-01-10,Kanto
5,104,7,2200,2023-01-12,Kyushu
6,102,10,1100,2023-01-15,Chubu
7,105,4,1800,2023-01-18,Kanto
8,103,7,1350,2023-01-20,Kyushu
9,101,10,1000,2023-01-22,Chubu
10,106,4,2500,2023-01-25,Kanto

クエリ結果と 2 つの CSV ファイルをよく見てください...
2 つの CSV ファイルが合体して出力されているのです...
employees テーブルが athena-sample-data-[あなたのバケット名]/csv-data/ の CSV を参照しているため、employees.csvsales_2023.csv は同じテーブルのデータとしてみなされてしまったということでした...
というわけで、データを追加する場合は同じ構造の新規ファイルを上記の S3 パスに配置すれば、データが追加されます(実際に INSERT 文を発行すると、同じ場所にファイルが作成されます)。

今回のバッドプラクティスは、Athena テーブルが参照している同じ場所に、コンテキストの異なる 2 つの CSV ファイルを配置してしまった点ですね...orz

まとめ

初めての AWS で行き当たりばったりだったのですが、何とか Athena を学べました。
AWS Skill Builder や Builders Lab での予習は役立ちましたが、実際に構築すると想定外の課題にぶつかりました。やはり実践が一番の学びだと身に沁みて感じました。

今回は、AWS Athena の基本的な部分であるテーブル作成や、クエリ実行などについて学びました。

次回は Parquet 化やパーティション設計、CTAS の活用など、もう少し踏み込んだ内容をご紹介します。

では、また次回。

GitHubで編集を提案

Discussion