Athena と Kinesis Data Firehose で S3 のログをクエリする
Kinesis Data Firehose でログを S3 に配信し、Athena でクエリします。カスタムプレフィックスを使ってパーティションを自動登録する方法を解説します。
Athena を使うと、サーバーをプロビジョニングせずに、S3 に保存されたオブジェクトへ直接 SQL クエリを実行できます。この記事では、Kinesis Data Firehose でログを S3 に配信し、Athena でクエリする一般的な構成を紹介します。

Kinesis Data Firehose 配信ストリームの作成
この構成では、2019 年 2 月に導入されたカスタム S3 プレフィックス機能を使用します。Firehose は S3 オブジェクトキーに Apache Hive 形式のプレフィックスを追加できるため、Athena の MSCK REPAIR TABLE で対応するパーティションを自動的に作成できます。
Create delivery stream を選択し、名前を入力します。


Direct PUT or other sources を選択します。

レコード処理の設定はスキップします。

配信先として Amazon S3 を選択します。

プレフィックスとエラープレフィックスを以下の形式で設定します。
- Prefix:
logs/!{timestamp:'year='yyyy'/month='MM'/day='dd'/hour='HH}/ - Error Prefix:
error_logs/!{timestamp:'year='yyyy'/month='MM'/day='dd'/hour='HH}/!{firehose:error-output-type}

要件に応じて Buffer size と Buffer interval を調整します。

ストレージコストを削減するため、GZIP 圧縮を使用します。

配信ストリーム用の IAM ロールを作成するか、既存のロールを選択します。

データのストリーミング
Kinesis Data Firehose の配信ストリームへプログラムからデータを送るには、AWS SDK for PHP: FirehoseClient#putRecord メソッドを使用します。
$client = new FirehoseClient([ 'region' => '<AWS_REGION>', 'version' => 'latest',]);
$data = [ 'log_id' => 12345, 'url' => 'https://example.com',];
$client->putRecord([ 'DeliveryStreamName' => '<YOUR_STREAM>', 'Record' => [ 'Data' => json_encode($data) . PHP_EOL, ],]);Athena テーブルの作成
Athena コンソールで Create table from S3 bucket data を選択します。

データベース名、テーブル名、Firehose が使用する S3 パスを入力します。

データフォーマットとして JSON を指定します。

データ構造に応じてカラムを定義します。

クエリのパフォーマンスを向上させるため、パーティション(例:year/month/day/hour)を設定します。
パーティショニングによりスキャンされるデータ量が最小限に抑えられ、コストが大幅に削減されます。

パーティションは以下のコマンドで読み込みます。

MSCK REPAIR TABLE {TABLE_NAME};Athena テーブルへのクエリ
パーティションが設定されていれば、データセット全体をスキャンする代わりに、特定の日付範囲を対象にクエリを実行できます。
SELECT *FROM table_nameWHERE year = 2019 AND month = 8 AND day = 30LIMIT 10;ベストプラクティス:
WHERE句には必ずパーティションキーを含める。- 不要なスキャンを避けるため、
LIMIT句を使用する。
まとめ
このパイプラインでは、Kinesis Data Firehose 経由でログを S3 に配信し、データベースのインフラをプロビジョニングせずに Athena からクエリできます。カスタム S3 プレフィックス機能を使って year=/month=/day=/hour= の下にオブジェクトを書き込むと、ログが 1 時間分増えるたびに ALTER TABLE ... ADD PARTITION を実行する必要がありません。MSCK REPAIR TABLE がパーティションを検出して登録します。
Firehose 配信ストリームの GZIP 圧縮はストレージ使用量を抑え、WHERE 句によるパーティションプルーニングはクエリごとのスキャン量を削減します。Athena はスキャンしたバイト数に応じて課金されるため、不要なデータを読み込まないことがコスト削減につながります。
データ量が増えたら、Firehose のバッファサイズと間隔を調整します。バッファを大きくすると、少数の大きな S3 オブジェクトが生成されるため、多数の小さなファイルを保存する場合よりも Athena のクエリ性能が向上する傾向があります。
Related posts
Kinesis Firehose の動的パーティショニングで NDJSON 処理を簡素化する
Kinesis Data Firehose の動的パーティショニングを使い、変換用の Lambda 関数を用意せずに NDJSON(改行区切り JSON)を S3 へ出力します。
AWS IoT Core における Kinesis Firehose のレコード区切り設定
IoT Core のトピックルールにある Firehose アクションで区切り文字を設定し、S3 にレコードを改行区切りで格納する方法を解説します。
SiteWise Edge Gateway で OPC UA データを Kinesis にストリーミングする
SiteWise Edge Gateway とカスタムの Greengrass コンポーネントを使い、OPC UA テレメトリを Kinesis Data Streams へ橋渡しします。
AWS Athena のパーティションプロジェクション
Athena のパーティションプロジェクションを使い、パーティションを Glue Data Catalog へ個別に追加せずにクエリする方法を解説します。
AWS IoT のペイロード値で Kinesis レコードをパーティショニングする
IoT トピックのペイロードに含まれる顧客 ID を Kinesis のパーティションキーとして使い、顧客ごとのレコード順序を維持する方法を解説します。
