📋

List Objectsに数日かかる世界からの脱却。20TB/日のデータを支えるS3インベントリ活用術

に公開

はじめに

こんにちは。Turing MLOpsチームの海老澤です。
自動運転AIを作るためには大規模なデータセットが必要です。
Turingでは「データセントリックAI」の考え方のもと、膨大なセンサーデータを活用し、大容量、高品質かつ多様性のある学習データセットの構築に取り組んでいます。
この大規模なデータセットで学習されたE2E自動運転は都内でも30分ほど走行できるレベルに到達しています。
https://zenn.dev/turing_motors/articles/bc6436727234ad

しかし、データセットの容量やファイル数が指数関数的に増加するにつれ、「ただファイルの一覧を取得するだけ」という標準的な操作が困難になってきました。通常の ListObjects APIでは、数億オブジェクト規模のバケットをスキャンすると並列化しても完了まで数日を要し、都度取得する方法はもはや現実的ではありません。
本記事では、この課題を解決するために導入した S3インベントリによるデータ管理基盤について解説します。

データセットの規模と課題

Turingの学習データセットは、複数台のカメラ画像、CANログ、地図情報など、多様なモダリティを組み合わせた構成になっています。これらはETLパイプラインを経てS3に格納され、学習環境へ同期されます。

当初は50時間程度だったデータ規模も、現在は数千時間規模へとスケールしました。こうなると、以下のような「当たり前の確認」ができなくなります。

  • 「新しいデータセットの合計サイズは?」
  • 「フォルダ内のファイル数は正常か?」
  • 「GPUクラスターのストレージ(lustre)の容量に、データセットを同期するだけの容量の空きがあるか?」

データセットの規模が大きくなると、ListObjects による集計ではスクリプトを工夫して実行しても時間がかかり、もはや「気軽に状況把握」できるレベルではなくなります。集計という「準備」に時間を取られ、本来の目的である「モデルの改善」という意思決定が遅れてしまう。これがS3インベントリ導入の最大の動機でした。

S3インベントリによる「棚卸し」の自動化

S3インベントリは、S3がマネージドにバケット内オブジェクトのメタデータ(サイズ、ストレージクラスなど)をレポートとして出力してくれる機能です。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/configure-inventory.html

最大のメリットは、「自前でList APIを叩き続ける代わりに、S3側に定期的な棚卸し(インベントリ作成)を任せ、その結果をDatabricks上のテーブルに格納し、SQLでクエリする」というアプローチへの転換です。

出力は日時でパーティションされ、manifest.json / manifest.checksum と、実データである data/*.parquet(※設定によりCSVも可)が生成されます 。

/
└── Parquet-test
    ├── 2025-10-26T01-00Z
    │   ├── manifest.checksum
    │   └── manifest.json
    ├── 2025-10-27T01-00Z
    │   ├── manifest.checksum
    │   └── manifest.json
    ├── data
    │   ├── 54cc32f0-c31d-4fc7-bbea-2cbd2e0b12c9.parquet
    │   └── b7c525a5-381d-4f14-ac09-0af91eb59ebf.parquet
    └── hive
        ├── dt=2025-10-26-01-00
        │   └── symlink.txt
        └── dt=2025-10-27-01-00
            └── symlink.txt

また、インベントリレポートは基本的に「その時点の全オブジェクトのスナップショット」です。日次で差分がほぼ無い場合、同じ内容が毎日重複して溜まることになります 。

ストレージコストを抑えるため、ライフサイクルポリシーで一定期間(Turingでは1週間)を過ぎたレポートは自動削除するように設計しています。

注意点として、S3インベントリの更新頻度は日次か週次を選択することができますが、いずれにせよリアルタイム性がないです。S3インベントリの結果を別のタスクで参照する場合には本番環境との整合性を考慮する必要があります。
リアルタイム性を補完する機能としてS3 Metadetaがあります。S3インベントリと比べるとコストがかかりますが、要件によってはこちらのサービスを使ってみてもいいかもしれません。

導入コストの考え方

S3インベントリのコストは非常に安価で、大きく2つの実行コストと、インベントリレポートの保存容量に分類できます。

実行コストは100万オブジェクトあたり USD 0.0025公式ドキュメントに記載されています 。
インベントリレポートはS3に保存され、費用はファイルサイズに応じて変動します。
ファイルサイズは、インベントリレポートに保存するメタデータの種類とファイル数によります。
S3のメトリクスで事前にファイル数を確認してコストを見積もりました。リリース後にもファイルが増えているため少し上振れてしまいましたが、概ね試算試算通りの結果でした。

今回の導入の目的はデータセットのサイズとファイル数を知ることでした。それぞれのファイルのサイズを知ることができれば集計することができるので、メタデータはサイズとストレージの種類のみにしました。レポートは毎日作成され長期で保存する必要がないので、保存期間を1週間に設定しました。

集計パイプライン:DatabricksによるData lakehouse運用

S3インベントリによって出力された大量のParquetファイルを効率よく扱うため、TuringではDatabricksを活用しています。
集計の粒度によって求められるものが異なるため、用途に合わせて以下の2段階のテーブル構成にしました。

外部テーブル(External Table):ファイル単位の詳細確認用

インベントリが出力したParquetに対して直接クエリを行う方式です。1オブジェクト1行で全ファイルのメタデータを保持しているため、特定のフォルダやファイルの容量を個別に確認したいケースに適しています。
一方で、データセット内のファイル数が1,000万件を超えることもあり、「あるデータセット全体の合計サイズ」のような集計クエリには時間がかかります。

集計テーブル(Delta Table):データセット単位のサマリ用

外部テーブルに対して集計クエリを実行し、その結果をDelta Tableとして格納する方式です。データセットごとの合計容量やファイル数が事前に計算されているため、即座に結果を取得できます。GUI/CLIからの頻繁なアクセスにも対応できます。
ただし集計済みのデータなので、個別ファイルのサイズを確認したい場合には外部テーブルを参照する必要があります。

更新フロー

Databricks Jobで日次でテーブルを更新しています。日ごとにパーティションされているmanifest.jsonから最新のパーティションのみをパースして外部テーブルを作成し、その結果をデータセット単位で集計してDelta Tableに反映します。
ユーザーは用途に応じてテーブルを使い分けることで、数億件のオブジェクト情報から必要な粒度の情報を数日ではなく数秒で取得できるようになりました。

GUI/CLIによる可視化

MLOpsチームではMLエンジニアがストレスなくデータを使えるよう、集計結果はGUI/CLI経由で提供しています。
DeltaTableにアクセスしS3インベントリの結果を取得できるAPIを作成し、GUI/CLIで共用しています。GUI/CLIで共通のオプションを提供し、用途に応じてユーザーが選択する事ができます。データセットの検索やソートの機能を提供し、ユーザーが手軽にデータセットの容量を確認できるようになりました。

TuringではAPIファーストで機能を提供しています。この文化が生まれた背景や設計などの詳細はこちらの記事で紹介しているので、ぜひご一読ください。
https://zenn.dev/turing_motors/articles/71f1e96311885c

まとめ

S3インベントリを導入することで、"Listを回して数日かけて集計"する世界から、"GUI/CLIで数秒で結果を取得する世界へ"移行できました。

データセントリックAIを推進する上で、データの品質だけでなく、それを支える「観測基盤」の構築は不可欠です。S3 インベントリはその第一歩として、手軽に導入することができて効果も実感できる機能でした。

Turingでは、さらに巨大化するデータセットを効率よく扱い、完全自動運転AIを一緒に作る仲間を募集しています。 興味のある方はぜひ採用ページからご応募ください!カジュアル面談やオフィス見学などライトな交流も大歓迎です!

Tech Blog - Turing

Discussion