こんにちは。クラウドソリューション事業部の石垣です。
2023年11月のアップデートで、S3サーバーアクセスログのオブジェクトキーの形式として日付ベースのパーティションが追加されましたが、何が嬉しかったのか改めて具体的に追ってみました。
S3サーバーアクセスログへのログオブジェクトキーの形式追加
2023年11月にログオブジェクトキーの形式として、日付ベースのパーティショニングに対応しました。
- 従来まで
- [DestinationPrefix][YYYY]-[MM]-[DD]-[hh]-[mm]-[ss]-[UniqueString]
- 選択できるようになった形式
- [DestinationPrefix][SourceAccountId]/[SourceRegion]/[SourceBucket]/[YYYY]/[MM]/[DD]/[YYYY]-[MM]-[DD]-[hh]-[mm]-[ss]-[UniqueString]
何が嬉しかったか
Athena等で分析用にクエリを流す際に、パーティション設定をすることで全件スキャンではなく特定の日付([YYYY]/[MM]/[DD])のログに対してクエリを実行できるようになりました。
Athenaの料金はスキャンしたデータ量に応じて課金されるため、不要なデータまで読み込むとコストが増加します。また、当然ながらスキャン量が増えるほどクエリの実行時間も長くなります。
例えば、1年分のS3アクセスログが保存されている場合に、
1WHERE day = '2026-07-06'というクエリを実行したとしても、パーティションがなければ1年分のログを読み込んだ上で7月6日のデータだけを抽出することになります。
一方、日付パーティションが設定されていれば、
1.../2026/07/06/配下だけを読み込めばいいので、不要なファイルをスキャンせずに済みます。
その結果、
- スキャンデータ量の削減
- Athenaのクエリコストの削減
- クエリ実行時間の短縮
につながります。
なぜ従来的な形式ではパーティションを分けられなかったか?
S3上のオブジェクトは、「フォルダ」のように見えても、実際にはオブジェクトキーという文字列で管理されています。
- [DestinationPrefix][YYYY]-[MM]-[DD]-[hh]-[mm]-[ss]-[UniqueString]
- [DestinationPrefix][SourceAccountId]/[SourceRegion]/[SourceBucket]/[YYYY]/[MM]/[DD]/[YYYY]-[MM]-[DD]-[hh]-[mm]-[ss]-[UniqueString]
も、S3から見るとどちらも1つのオブジェクトキーであり、「フォルダ」という実体は存在しません。
「S3はフラットな構造なのだから、/でパーティションを切れるのであれば、-を区切りとしてもパーティションを作れそうでは?」と思われる方もいるかもしれません。
しかし、これはAthena(Hive)のパーティションの考え方を知ると理由が分かります。
Athenaのパーティションは「Path」単位
Athenaは内部でSQLエンジンとしてTrinoを利用し、テーブルやパーティションはHive互換のメタデータで管理しています。
そしてHiveでは、1つのパーティションは1つのLocation(Path)として管理されます。
このPathはHadoop Commonのorg.apache.hadoop.fs.Pathで表現されており、公式ドキュメントにも
Path strings use slash as the directory separator.
と記載されています。
参考
つまり、
1logs/2026/07/06/access.logは
1logs
2└──2026
3 └──07
4 └──06
5 └──access.logという階層構造になります。
一方、
1logs/2026-07-06-10-47-22-xxxxは
1logs
2└──2026-07-06-10-47-22-xxxxという1つのPath要素として扱われます。
ここで重要なのは、dayでパーティションを設定したいと思った場合に、2026と07と06がハイフンで繋がれていることではなく、10の後もハイフンで後ろと繋がっていることです。
実際に確認してみた
本当に従来形式ではパーティションが利用できないのか、Athenaで検証してみました。
テーブルはRegexSerDeでS3サーバーアクセスログを読み込む一般的な構成とし、Partition Projectionを利用して日付パーティションを定義しています。
1PARTITIONED BY (day STRING)
2
3TBLPROPERTIES (
4 'projection.enabled'='true',
5 'projection.day.type'='date',
6 'projection.day.range'='2026-07-01,NOW',
7 'projection.day.format'='yyyy-MM-dd',
8 'storage.location.template'='s3://[bucketName]/legacy/${day}'
9)ここでポイントとなるのは
1storage.location.template =
2s3://[bucketName]/legacy/${day}となります。
例えば、
1WHERE day = '2026-07-06'で検索すると、Athenaは
1s3://[bucketName]/legacy/2026-07-06をパーティションのLocationとして解決します。
もし単純なPrefix検索であれば、
1legacy/2026-07-06-10-47-22-...という従来形式のログにも一致しそうです。
しかし、実際には検索結果は0件でした。
「なぜ0件なのか?」を調べるために、Athenaがこの時にどういうクエリを投げていたかをS3アクセスログを取得して確認しました。
AthenaのAPIコールは以下となっていました。
1GET /?list-type=2&prefix=legacy/2026-07-06/AthenaはパーティションのLocationをPathとして解釈し、結果として legacy/2026-07-06/ をPrefixとしたListObjects APIを発行していました。
まとめ
今回調べてみて、2023年に追加されたログオブジェクトキー形式は、Athena(Hive)のパーティションモデルを考えると非常に納得感のあるアップデートでした。
これからS3サーバーアクセスログをS3へ出力するのであれば、日付ベースのパーティション形式を選択しておくのがいいと思います。
一方で、2026年6月にはS3サーバーアクセスログのCloudWatch Logs配信も追加されました。CloudWatch Logs Insightsによる検索や、S3 Tablesとの連携など、従来のS3バケットへの配信とは異なるメリットもあります。
まだ登場したばかりの機能ではありますが、これから新しくS3サーバーアクセスログを活用するのであれば、S3への直接配信だけでなく、CloudWatch Logs配信も選択肢として検討する価値がありそうです。
CloudWatch Logs配信を含めたアップデートをまとめた記事は以下。
https://www.seeds-std.co.jp/blog/creators/s3accesslog-202607/
