本ページは、AWS に関する個人の勉強および勉強会で使用することを目的に、AWS ドキュメントなどを参照し作成しておりますが、記載の誤り等が含まれる場合がございます。
最新の情報については、AWS 公式ドキュメントをご参照ください。
標準的な SQL を使用して Amazon Simple Storage Service (Amazon S3) 内のデータを直接分析することを容易にするインタラクティブなクエリサービスです。
Amazon Athenaを理解する公式ドキュメントは次のとおりです。
Athena をグラレコで解説||builders.flash
【AWS Black Belt Online Seminar】Amazon Athena(YouTube)(1:00:43)
第二十回 ちょっぴりDD -Amazon Athena であっちこっちのデータを一括分析しよう
第三十二回 ちょっぴりDD - Amazon Athena (Iceberg) x dbt ではじめるデータ分析!
Amazon Athena Federated Query 経由で Amazon DynamoDB のデータを Amazon QuickSight で可視化するハンズオン
Amazon Athena ACID transaction workshop
CloudFront ハンズオン>Athena でのログ集計
AWS WAF を使って Web アプリケーションの防御を強化する>AWS WAF ログを調査する
Amazon Athenaを導入する主なメリットは以下の3つです。
AWSマネジメントコンソール上で簡単にSQLを記述し、実行することができます。
基本となるデータソースは次の2つです。
そのほかのデータソースコネクタを使用することで、次のようなものも接続できます。
Athenaはクエリでスキャンしたデータ量による従量課金であるため、スキャンするデータ量を制限できるようにすることは、コスト最適化の点で重要です。 スキャンするデータ量を制限する方法として、パーティションと呼ばれる一定のグループにデータを分けて整理しておくことで、目的のデータを探すのに読み込むデータを削減できます。 代表的なパーティションが、S3バケットのプレフィックスを年・月の単位にすることです。 具体的には、s3://amzn-s3-demo-bucket/hogehoge/
という単一のプレフィックスに保存するのではなく、s3://amzn-s3-demo-bucket/2025/01/
といったプレフィックスにして保存します。こうすることで、2025年1月のデータを読み込みたい場合、バケット全体から探す必要がなくなります。
パーティションの分け方には2種類あります。
s3://amzn-s3-demo-bucket/year=2025/month=01/day=01/myfile.csv
MSCK REPAIR TABLE
が必要s3://amzn-s3-demo-bucket/2025/01/01/myfile.csv
ALTER TABLE ADD PARTITION
でパーティションを手動で追加できるS3バケットのプレフィックスでパーティション化したら、あとはAthenaでテーブルを作成します。 年(year)の範囲(range)にNOWを指定すると、範囲指定がクエリ実行時の年となるため、新しいパーティションを追加する手間がありません。
CREATE EXTERNAL TABLE my_test_table (
...
)
...
PARTITIONED BY (
year string,
month string,
day string
)
LOCATION "s3://amzn-s3-demo-bucket/test_table/"
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.year.type' = 'date',
'projection.year.format' = 'yyyy',
'projection.year.range' = '2024,NOW',
'projection.month.type' = 'integer',
'projection.month.range' = '1,12',
'projection.month.digits' = '2',
'projection.day.type' = 'integer',
'projection.day.range' = '1,31',
'projection.day.digits' = '2',
/* 非Hive形式 */
'storage.location.template' = 's3://amzn-s3-demo-bucket/test_table/${year}/${month}/${day}'
/* Hive形式
'storage.location.template' = 's3://amzn-s3-demo-bucket/test_table/year=${year}/month=${month}/day=${day}'
*/
);
過去に実行したクエリをテンプレートとして再利用可能な形で保存することができます。クエリエディタで実行したクエリ似たしいて、「名前をつけて保存」ができます。
詳細は、「保存されたクエリを使用する」を参照してください。
テンプレートは保存したクエリをそのまま実行する用途なのに対して、ビューはさらにデータの絞り込みや必要な項目のみにしたい場合に有効です。
作成するには、CREATE VIEW
を使用します。
CREATE VIEW name_salary AS
SELECT
employees.name,
salaries.salary
FROM employees, salaries
WHERE employees.id = salaries.id
詳細は、「ビューを使用する」を参照してください。
S3以外にあるデータソースに対してもクエリが実行できるようになります。 この機能を使うことで、複数のデータソースのデータを横断的に分析ができるようになります。
主なデータソースは次のとおりです。詳細はドキュメント「使用可能なデータソースコネクタ」を参照してください
動画:「Amazon Athena Federated Query」
動画: Amazon QuickSight で Amazon Athena フェデレーティッドクエリの結果を分析する
CTASは、「シータス」と読みます。(AWS Black Belt Online Seminarより)
CREATE TABLE AS SELECT (CTAS) クエリは、SELECTステートメントの結果から、Athenaで新しいテーブルを作成します。作成されたテーブルのデータはS3に保存されます。
CTASを使うユースケースとしては次のようなものがあります
CTASの例
CREATE TABLE new_table
WITH (
format = 'Parquet',
write_compression = 'SNAPPY')
AS SELECT *
FROM old_table
WHERE condition;
Amazon SageMaker AI を使用して Machine Learning (ML) 推論を実行する SQL ステートメントの記述に Athena を使用できます。
USING EXTERNAL FUNCTION ml_function_name (variable1 data_type[, variable2 data_type][,...])
RETURNS data_type
SAGEMAKER 'sagemaker_endpoint'
SELECT ml_function_name()
レコードまたはレコードのグループを処理するためのカスタム関数を作成できます。
USING EXTERNAL FUNCTION UDF_name(variable1 data_type[, variable2 data_type][,...])
RETURNS data_type
LAMBDA 'lambda_function_name_or_ARN'
[, EXTERNAL FUNCTION UDF_name2(variable1 data_type[, variable2 data_type][,...])
RETURNS data_type
LAMBDA 'lambda_function_name_or_ARN'[,...]]
SELECT [...] UDF_name(expression) [, UDF_name2(expression)] [...]
ワークグループとは、ユーザーやチームでクエリの実行やクエリ実行履歴の保存環境を分離できる仮想的なグループです。
ワークグループを使用すると、以下の管理ができます。
Athenaでは、ESRIの Java Geometry Libraryをサポートしています。
詳細は、「地理空間データをクエリする」、「例: 地理空間クエリ」を参照してください。
実装例:ワークグループ作成のCDKコード(クリックしてください)
import { Construct } from 'constructs';
import * as cdk from 'aws-cdk-lib';
import {
aws_s3 as s3,
aws_athena as athena,
} from 'aws-cdk-lib';
export class AthenaStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Athenaクエリ結果格納バケット
const athenaQueryResultBucket = new s3.Bucket(this, 'AthenaQueryResultBucket', {
bucketName: ['athena-query-result', accountId].join('-') ,
accessControl: s3.BucketAccessControl.PRIVATE,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: props.isAutoDeleteObject ? cdk.RemovalPolicy.DESTROY : cdk.RemovalPolicy.RETAIN,
autoDeleteObjects: props.isAutoDeleteObject,
});
athenaQueryResultBucket.addLifecycleRule({
//expiration: cdk.Duration.days(60),
abortIncompleteMultipartUploadAfter: cdk.Duration.days(7), // 不完全なマルチパートアップロードの削除
transitions: [
{
storageClass: s3.StorageClass.INTELLIGENT_TIERING,
transitionAfter: cdk.Duration.days(0),
},
],
});
// Athena ワークグループ
const athenaWorkGroup = new athena.CfnWorkGroup(this,'athenaWorkGroup',{
name: ['athenaWorkGroup',accountId].join('-'),
description: 'description....',
workGroupConfiguration: {
resultConfiguration: {
outputLocation: `s3://${athenaQueryResultBucket.bucketName}/result-data`,
},
},
},
);
}
}
実装例:ALBログテーブル作成のCDKコード(クリックしてください)
const applicationLogsDatabase = new glue.CfnDatabase(scope, 'ApplicationLogsDatabase', {
catalogId: accountId,
databaseInput: {
name: 'application_logs_database',
},
});
// Glue Table (ALB Access Logs) with Partition Projection
const albAccessLogsTable = new glue.CfnTable(scope, "AlbAccessLogsTables", {
databaseName: 'application_logs_database',
catalogId: cdk.Stack.of(scope).account,
tableInput: {
name: 'alb_access_logs_table',
tableType: "EXTERNAL_TABLE",
parameters: {
"projection.enabled": true,
"projection.date.type": "date",
"projection.date.range": "NOW-1YEARS, NOW+9HOUR",
"projection.date.format": "yyyy/MM/dd",
"projection.date.interval": "1",
"projection.date.interval.unit": "DAYS",
"serialization.encoding": "utf-8",
"storage.location.template": `s3://amzn-s3-demo-bucket/AWSLogs/${cdk.Stack.of(scope).account}/elasticloadbalancing/${cdk.Stack.of(this).region}/` + "${date}/",
},
storageDescriptor: {
columns: [
{"name": "type","type": "string"},
{"name": "time","type": "string"},
{"name": "elb", "type": "string"},
{"name": "client_ip","type": "string"},
{"name": "client_port","type": "int"},
{"name": "target_ip","type": "string"},
{"name": "target_port","type": "int"},
{"name": "request_processing_time","type": "double"},
{"name": "target_processing_time","type": "double"},
{"name": "response_processing_time","type": "double"},
{"name": "elb_status_code","type": "int"},
{"name": "target_status_code","type": "string"},
{"name": "received_bytes","type": "bigint"},
{"name": "sent_bytes","type": "bigint"},
{"name": "request_verb","type": "string"},
{"name": "request_url","type": "string"},
{"name": "request_proto","type": "string"},
{"name": "user_agent","type": "string"},
{"name": "ssl_cipher","type": "string"},
{"name": "ssl_protocol","type": "string"},
{"name": "target_group_arn","type": "string"},
{"name": "trace_id","type": "string"},
{"name": "domain_name","type": "string"},
{"name": "chosen_cert_arn","type": "string"},
{"name": "matched_rule_priority","type": "string"},
{"name": "request_creation_time","type": "string"},
{"name": "actions_executed","type": "string"},
{"name": "redirect_url","type": "string"},
{"name": "lambda_error_reason","type": "string"},
{"name": "target_port_list","type": "string"},
{"name": "target_status_code_list","type": "string"},
{"name": "classification","type": "string"},
{"name": "classification_reason","type": "string"},
],
inputFormat: "org.apache.hadoop.mapred.TextInputFormat",
outputFormat: "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
serdeInfo: {
serializationLibrary: "org.apache.hadoop.hive.serde2.RegexSerDe",
parameters: {
'serialization.format': '1',
'input.regex': '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\s]+?)\" \"([^\s]+)\" \"([^ ]*)\" \"([^ ]*)\"'
}
},
location: `s3://amzn-s3-demo-bucket/AWSLogs/${cdk.Stack.of(scope).account}/elasticloadbalancing/${cdk.Stack.of(this).region}`,
},
partitionKeys: [
{"name": "date", "type": "string"},
]
}
})
Athenaでのパフォーマンスチューニングの詳細については、「Athena のパフォーマンスを最適化する」や「追加リソース」を参照してください。
Athenaは、データレイク戦略の中核として位置づけられ、S3に蓄積された様々な形式のデータを迅速に分析する強力なツールです。ETLパイプラインやダッシュボード構築などと組み合わせることで、データ駆動型の意思決定を促進するプラットフォームとして活用できます。 データ分析の需要が高まる中、Athenaはその柔軟性と拡張性により、ますます重要な役割を担っていくと思われます。