Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみた
こんにちは、製造ビジネステクノロジー部の若槻です。
Amazon S3 バケット内のオブジェクトの ストレージクラス を設定すると、オブジェクトのストレージコスト、パフォーマンス、可用性を最適化することができます。
このストレージクラスを標準(Standard)以外に移行したオブジェクトは Amazon Athena でクエリできるのでしょうか?ふと気になりました。
そこで今回は Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみました。
最初にまとめ
調査の結果、ストレージクラスおよび復元状態(未復元、復元済)によって、Amazon Athena でのクエリ可否は下記のようになりました。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Standard | STANDARD |
- | はい | 汎用 |
Amazon S3 Intelligent-Tiering | INTELLIGENT_TIERING |
はい | はい | 不明 |
Amazon S3 Express One Zone | EXPRESS_ONEZONE |
はい | はい | 高速アクセス |
Amazon S3 Standard-Infrequent Access | STANDARD_IA |
はい | はい | 低頻度アクセス |
Amazon S3 One Zone-Infrequent Access | ONEZONE_IA |
はい | はい | 低頻度アクセス |
Amazon S3 Glacier Instant Retrieval | GLACIER_IR |
はい | はい | アーカイブ |
Amazon S3 Glacier Flexible Retrieval | GLACIER |
いいえ | はい | アーカイブ |
Amazon S3 Glacier Deep Archive | DEEP_ARCHIVE |
いいえ | はい | アーカイブ |
なおこのクエリ可否の一覧は、後述の検証結果とドキュメントの確認結果を組み合わせてまとめたものとなります。
検証
各ストレージクラスのオブジェクトを実際に Amazon Athena でクエリする検証を行います。
環境準備
検証環境の準備として、AWS CDK で検証に必要なリソースを作成します。
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as athena from 'aws-cdk-lib/aws-athena';
import * as glue_alpha from '@aws-cdk/aws-glue-alpha';
import { Construct } from 'constructs';
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
/**
* Ahena ワークグループ
*/
new athena.CfnWorkGroup(this, 'WorkGroup', {
name: 'workGroup',
});
/**
* S3 バケット
*/
const bucket = new s3.Bucket(this, 'Bucket');
/**
* Glue データベース
*/
const database = new glue_alpha.Database(this, 'Database');
/**
* Glue テーブル
*/
new glue_alpha.S3Table(this, 'S3Table', {
database,
bucket,
dataFormat: glue_alpha.DataFormat.CSV,
columns: [
{
name: 'storageClass',
type: glue_alpha.Schema.STRING,
},
],
});
}
}
オブジェクトのアップロード
aws s3api put-object
コマンドを使って次のようにストレージクラスごとのオブジェクトをアップロードします。
aws s3api put-object \
--bucket ${BUCKET_NAME} \
--key "${STORAGE_CLASS}.csv" \
--body temp.csv \
--content-type text/csv \
--storage-class ${STORAGE_CLASS}
なお、ストレージクラスが 8 つと多いので次のようなスクリプトを作成してアップロードしました。
スクリプト全体と実行結果
#!/bin/bash
# バケット名が指定されているか確認
if [ $# -eq 0 ]; then
echo "Error: Bucket name not provided."
echo "Usage: $0 <bucket-name>"
exit 1
fi
BUCKET_NAME=$1
STORAGE_CLASSES=(
"STANDARD"
"INTELLIGENT_TIERING"
"EXPRESS_ONEZONE"
"STANDARD_IA"
"ONEZONE_IA"
"GLACIER_IR"
"GLACIER"
"DEEP_ARCHIVE"
)
echo "Using bucket: $BUCKET_NAME"
for STORAGE_CLASS in "${STORAGE_CLASSES[@]}"; do
echo "Processing $STORAGE_CLASS..."
# 一時ファイルを作成
echo "$STORAGE_CLASS" > temp.csv
# ファイルをアップロード
aws s3api put-object \
--bucket ${BUCKET_NAME} \
--key "${STORAGE_CLASS}.csv" \
--body temp.csv \
--content-type text/csv \
--storage-class ${STORAGE_CLASS}
# アップロードの確認
if [ $? -eq 0 ]; then
echo "$STORAGE_CLASS.csv uploaded successfully."
else
echo "Failed to upload $STORAGE_CLASS.csv"
fi
# 一時ファイルを削除
rm temp.csv
done
echo "All files processed."
$ ./upload_storage_classes.sh ${BUCKET_NAME}
Using bucket: main-bucket83908e77-11mc4fvqobms
Processing STANDARD...
{
"ETag": "\"e2f925a6325dd5feb059876e6bd94540\"",
"ServerSideEncryption": "AES256"
}
STANDARD.csv uploaded successfully.
Processing INTELLIGENT_TIERING...
{
"ETag": "\"ceff6c81cfc199c8dacb7e88eedf8b23\"",
"ServerSideEncryption": "AES256"
}
INTELLIGENT_TIERING.csv uploaded successfully.
Processing EXPRESS_ONEZONE...
An error occurred (InvalidStorageClass) when calling the PutObject operation: The storage class you specified is not valid
Failed to upload EXPRESS_ONEZONE.csv
Processing STANDARD_IA...
{
"ETag": "\"2bdfd4495f86b20f6a9443344e8247db\"",
"ServerSideEncryption": "AES256"
}
STANDARD_IA.csv uploaded successfully.
Processing ONEZONE_IA...
{
"ETag": "\"b19caced51fdd670ee4c01d7aa21e6a6\"",
"ServerSideEncryption": "AES256"
}
ONEZONE_IA.csv uploaded successfully.
Processing GLACIER_IR...
{
"ETag": "\"87b51a4dea2cbac265462544956fc539\"",
"ServerSideEncryption": "AES256"
}
GLACIER_IR.csv uploaded successfully.
Processing GLACIER...
{
"ETag": "\"5cfbeb7f21290d361ec2e49764b92852\"",
"ServerSideEncryption": "AES256"
}
GLACIER.csv uploaded successfully.
Processing DEEP_ARCHIVE...
{
"ETag": "\"d38ff4a3726ae2c64b35f13509215b9c\"",
"ServerSideEncryption": "AES256"
}
DEEP_ARCHIVE.csv uploaded successfully.
All files processed.
ここで、Express One Zone ストレージクラスのオブジェクトのアップロード時にのみ An error occurred (InvalidStorageClass) when calling the PutObject operation: The storage class you specified is not valid
というエラーが発生しました。ドキュメントによるとこのストレージクラスのみ「ディレクトリバケット」という通常のバケットとは異なるバケットタイプを必要とするとのこと。
しかしこのストレージクラスについては後述の通り検証せずとも Amazon Athena でのクエリが可能とのことなので今回は検証を省略します。
結果として 7 つのストレージクラスのオブジェクトがアップロードされました。
これらのオブジェクトを対象に Amazon Athena でクエリを実行してみます。
未復元でクエリを実行
オブジェクトをアップロードした S3 バケットのテーブルに対して Amazon Athena で SELECT
クエリを実行すると次のような結果となりました。
クエリできたのは下記の 5 つのストレージクラスのオブジェクトでした。
- Amazon S3 Standard
- Amazon S3 Intelligent-Tiering
- Amazon S3 Standard-Infrequent Access
- Amazon S3 One Zone-Infrequent Access
- Amazon S3 Glacier Instant Retrieval
結論
Amazon S3 Intelligent-Tiering
検証では未復元でクエリが可能でしたが、このストレージクラスはアクセスの無い期間応じて自動的に最適なストレージクラスに移行されます。30日および90日間アクセスが無く低頻度アクセス層に移行された場合にクエリ可否が変わるのでしょうか?
下記の re:Post によるとオブジェクトが低頻度アクセス層に移行された場合にはレイテンシーが大きく可能性はあるがクエリ可能とのエキスパート回答がありました。
よって未復元でもクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Intelligent-Tiering | INTELLIGENT_TIERING |
はい | はい | パターン不明/可変 |
Amazon S3 Express One Zone
今回検証はできませんでしたが、アップデート情報およびドキュメントによると未復元のでクエリが可能なようです。
よって未復元でもクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Express One Zone | EXPRESS_ONEZONE |
はい | はい | 高速アクセス |
Amazon S3 Standard-Infrequent Access
検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Standard-Infrequent Access | STANDARD_IA |
はい | はい | 低頻度アクセス |
Amazon S3 One Zone-Infrequent Access
検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 One Zone-Infrequent Access | ONEZONE_IA |
はい | はい | 低頻度アクセス |
Amazon S3 Glacier Instant Retrieval
検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Glacier Instant Retrieval | GLACIER_IR |
はい | はい | アーカイブ |
Amazon S3 Glacier Flexible Retrieval
アップデート情報およびドキュメントによると復元済でのクエリが可能なようです。また検証では未復元ではクエリができませんでした。
よって復元済でのみクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Glacier Flexible Retrieval | GLACIER |
いいえ | はい | アーカイブ |
ちなみに復元されたオブジェクトをクエリするためにはテーブルプロパティ 'read_restored_glacier_objects' = 'true'
を設定する必要があるので注意しましょう。
Amazon S3 Glacier Deep Archive
アップデート情報およびドキュメントによると復元済でのクエリが可能なようです。また検証では未復元ではクエリができませんでした。
よって復元済でのみクエリ可能とここでは判断します。
ストレージクラス名 | ストレージクラス識別子 | 未復元で クエリ可能? |
復元済で クエリ可能? |
用途 |
---|---|---|---|---|
Amazon S3 Glacier Deep Archive | DEEP_ARCHIVE |
いいえ | はい | アーカイブ |
ちなみに復元されたオブジェクトをクエリするためにはテーブルプロパティ 'read_restored_glacier_objects' = 'true'
を設定する必要があるので注意しましょう。
おわりに
Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみました。すべてのパターンの検証はできておらずドキュメント頼りの部分もあり若干ふわっとしていますが、古いデータのストレージコストを下げつつ時々分析に使用したいというユースケースはあると思うので参考にはなるのではないでしょうか。
ちなみにオブジェクトをどのストレージクラスに移行されるかの判断には次の記事が参考になるので必要時に参照してみてください。
参考
以上