S3 の「/」は本当にフォルダなのか - フラットな名前空間の真実とプレフィックスの仕組み

S3 にはフォルダという概念が存在せず、オブジェクトキーの「/」は単なる文字列の一部であるという事実から、プレフィックス検索の仕組み、コンソールがフォルダに見せるトリック、キー設計のベストプラクティスを解説します。

S3 にフォルダは存在しない

S3 のデータモデルは、バケットとオブジェクトの 2 階層だけで構成されるフラットな名前空間です。ファイルシステムのようなディレクトリ階層は存在しません。オブジェクトキー images/2024/photo.jpg は、「images フォルダの中の 2024 フォルダの中の photo.jpg」ではなく、「images/2024/photo.jpg という名前の 1 つのオブジェクト」です。「/」はキー名の一部であり、ファイルシステムのパス区切り文字とは本質的に異なります。この事実を確認する簡単な方法があります。AWS CLI で aws s3api list-objects-v2 --bucket my-bucket を実行すると、すべてのオブジェクトがフラットなリストとして返されます。フォルダという概念は一切現れません。一方、aws s3 ls s3://my-bucket/ を実行すると、あたかもフォルダ構造があるかのように表示されます。これは s3 コマンド (高レベルコマンド) が、「/」をデリミタとして使用し、共通プレフィックスをフォルダのように表示しているだけです。

コンソールがフォルダに見せるトリック

AWS マネジメントコンソールの S3 画面では、フォルダアイコンが表示され、フォルダの作成ボタンもあります。しかし、コンソールで「フォルダを作成」すると、実際には末尾が「/」のゼロバイトオブジェクト (例: images/) が作成されます。このオブジェクトは、コンソールがフォルダとして表示するためのマーカーに過ぎません。フォルダマーカーを削除しても、そのプレフィックスを持つオブジェクトは影響を受けません。images/ オブジェクトを削除しても、images/photo.jpg は存在し続けます。逆に、images/photo.jpg をアップロードすれば、images/ マーカーがなくてもコンソールは images フォルダを表示します。コンソールは ListObjectsV2 API の Delimiter パラメータに「/」を指定し、CommonPrefixes (共通プレフィックス) をフォルダとして表示しています。この仕組みを理解していないと、「フォルダを削除したのに中のファイルが消えない」「フォルダを作成していないのにフォルダが表示される」という現象に困惑します。

プレフィックスとパフォーマンスの関係

S3 のプレフィックスは、パフォーマンスに直接影響します。S3 は 2018 年にパフォーマンスの大幅な改善を行い、プレフィックスごとに秒間 5,500 GET リクエストと 3,500 PUT リクエストを処理できるようになりました。ここでの「プレフィックス」は、オブジェクトキーの最初の「/」までの部分ではなく、キー全体のうち最後の「/」より前の部分です。たとえば、images/2024/01/photo.jpg のプレフィックスは images/2024/01 です。つまり、プレフィックスを分散させれば、バケット全体のスループットを事実上無制限に拡張できます。1 つのプレフィックスに秒間 5,500 GET が上限でも、100 個のプレフィックスに分散すれば秒間 55 万 GET が可能です。2018 年以前は、S3 のパーティショニングがキーの先頭文字に基づいていたため、キーの先頭にランダムなハッシュを付加する (例: a1b2c3/images/photo.jpg) というベストプラクティスがありました。現在はこの対策は不要で、S3 が自動的にパーティションを最適化します。

オブジェクトキー設計のベストプラクティス

オブジェクトキーの設計は、S3 の運用効率に大きく影響します。第 1 に、キーの命名規則を統一することです。日付ベースのキー (logs/2024/01/15/access.log) は、時系列データの管理に適しています。S3 のライフサイクルルールはプレフィックスベースで適用されるため、日付をプレフィックスに含めれば、古いデータを自動的に Glacier に移行したり削除したりできます。第 2 に、キーに特殊文字を避けることです。S3 のオブジェクトキーには UTF-8 の任意の文字を使用できますが、スペース、日本語、特殊記号を含むキーは、URL エンコーディングの問題を引き起こすことがあります。英数字、ハイフン、アンダースコア、スラッシュに限定するのが安全です。第 3 に、キーの長さを意識することです。オブジェクトキーの最大長は 1,024 バイトです。深いフォルダ構造を模倣して長いキーを使用すると、この上限に近づきます。また、ListObjectsV2 のレスポンスにはキー名が含まれるため、キーが長いとレスポンスサイズが増加し、ネットワーク帯域を消費します。

S3 Select とフラットな名前空間の活用

S3 のフラットな名前空間は、従来のファイルシステムの概念に慣れた開発者には違和感がありますが、大規模データ処理では大きな利点があります。フラットな名前空間では、ディレクトリのメタデータ管理が不要なため、数十億個のオブジェクトを格納してもパフォーマンスが劣化しません。ファイルシステムでは、1 つのディレクトリに数百万個のファイルがあると、ディレクトリのメタデータ読み込みだけで数秒かかることがあります。S3 Select は、オブジェクトの中身を S3 側で SQL クエリで絞り込み、必要なデータだけを返す機能です。CSV や JSON 形式のオブジェクトに対して SELECT 文を実行でき、データ転送量を大幅に削減できます。たとえば、1GB の CSV ファイルから特定の列だけを抽出する場合、S3 Select を使えば数 MB のデータだけが転送されます。S3 Select の料金はスキャンしたデータ量 (0.002 USD/GB) と返却したデータ量 (0.0007 USD/GB) で計算されるため、データ転送料金の削減と合わせてコスト効率が高くなります。S3 の設計パターンを体系的に学ぶには、専門書籍 (Amazon)が参考になります。