Athena のパーティションが分からなかったのでやってみた

Athena のパーティションが分からなかったのでやってみた

Clock Icon2025.07.21

Athena の パーティションという概念がよくわからなかったので、やってみました。

Athena パーティションとは?

パーティションとは、S3 オブジェクトがきちんとフォルダ分けしてある状態のことです。

  • パーティションなしの状態 -> オブジェクトがフォルダ分けされておらず、同じ階層に保存されている
パーティションなしの例
s3://<バケット名>/sample_data_1.csv
s3://<バケット名>/sample_data_2.csv
s3://<バケット名>/sample_data_3.csv
s3://<バケット名>/sample_data_4.csv
  • パーティションありの状態 -> オブジェクトがきちんとフォルダ分けされている(以下の例だと、月毎に分類されている)
パーティションありの例
s3://<バケット名>/2025/06/sample_data_1.csv
s3://<バケット名>/2025/06/sample_data_2.csv
s3://<バケット名>/2025/07/sample_data_3.csv
s3://<バケット名>/2025/08/sample_data_4.csv

上記のように、フォルダ分けすることをパーティション化と呼んでいます。パーティションが英語で Partition (訳:分割) という意味なので、本当にそのままですね。
オブジェクトをパーティションに区切って保存するということです。

パーティションに分けるメリット

パーティションに分けることで、Athena からのスキャン量を削減できるというメリットがあります。
パーティション化されていない場合、S3 の調べたい階層のデータを全てスキャンする必要があります。一方で階層分けされていれば、その階層だけ絞り込んで検索することが可能になります。
結果的にスキャン量が減り、コストも削減できます。フォルダ分割するだけで結構なメリットがあるんですね。

なお、パーティショニングについての説明は、以下公式ドキュメントにも記載がありますのでご参照ください。

クエリを実行する際に Athena がスキャンする必要があるデータ量を減らすための 2 つの方法として、パーティション化とバケット化があります。... スキャンするデータ量を減らすことは、パフォーマンスの向上とコストの削減につながります。

パーティショニングとバケット化を使用する

パーティショニングとは、データの特定のプロパティに基づいて、Amazon S3 上のディレクトリ(または「プレフィックス」)にデータを整理することを意味します。このようなプロパティはパーティションキーと呼ばれます。一般的なパーティションキーは、日付、または年や月などの時間単位です。

パーティション化とは

やってみた

S3 バケット作成

デフォルト設定で S3 バケットを作成します。

スクリーンショット 2025-07-11 15.34.03

データセットの作成

以下 4 つのサンプルデータを用意します。

sample_data_1.csv
TeamID,prefecture,point
TEAM_A,okinawa,100
TEAM_B,tokyo,200
sample_data_2.csv
TeamID,prefecture,point
TEAM_C,okinawa,300
TEAM_D,tokyo,400
sample_data_3.csv
TeamID,prefecture,point
TEAM_E,okinawa,500
TEAM_F,tokyo,600
sample_data_4.csv
TeamID,prefecture,point
TEAM_G,okinawa,700
TEAM_H,tokyo,800

作成したサンプルデータを S3 にアップロードしておきます。なお、現時点ではフォルダを作らず、バケット直下にオブジェクトを配置します。

スクリーンショット 2025-07-12 15.18.40

Athena からクエリしてみる

Athena クエリエディタにて以下の CREATE TABLE 文を実行します。
本クエリは、Athena の default データベースにテーブル test_table を作成するスクリプトになります。
LOCATION 句 には前項で作成済みの S3 バケット(test-athena-partitioning-0711) を指定しています。

CREATE EXTERNAL TABLE IF NOT EXISTS `default`.`test_table` (
  `TeamID` string,
  `prefecture` string,
  `point` int
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES ('field.delim' = ',')
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://test-athena-partitioning-0711/'
TBLPROPERTIES (
  'classification' = 'csv',
  'skip.header.line.count' = '1'
);

※補足:上記の CREATE TABLE 文はコンソールからも作成できます。試される場合は下記ブログをご参照ください。
https://dev.classmethod.jp/articles/querying-multiple-s3-buckets-with-union/#athena-%25E3%2583%2586%25E3%2583%25BC%25E3%2583%2596%25E3%2583%25AB%25E4%25BD%259C%25E6%2588%2590

上記クエリを実行後、default データベースに test_table が作成されていることが確認できました。

スクリーンショット 2025-07-11 15.46.14

Athena から S3 をクエリするためのテーブルが作成できたので、SELECT で test_table を全クエリしてみます。
その結果、以下画像の通り、4つのサンプルデータのすべてのレコード(合計8レコード)が取得できました。また、スキャン量は 0.23 KB であることがわかります。
スクリーンショット 2025-07-12 15.42.04

パーティショニングする

それでは続いて、パーティショニングして Athena からクエリを実行してみます。
まずは S3 をフォルダ分けします。フォルダ階層は以下のように月毎に分けてみました。

スクリーンショット 2025-07-12 15.51.07

S3 の階層構造
s3://test-athena-partitioning-0711/2025/06/sample_data_1.csv
s3://test-athena-partitioning-0711/2025/06/sample_data_2.csv
s3://test-athena-partitioning-0711/2025/07/sample_data_3.csv
s3://test-athena-partitioning-0711/2025/08/sample_data_4.csv

ちなみに、このフォルダ分けした状態で全クエリしても、全てのサンプルデータ情報(合計8レコード)が返却されます。

スクリーンショット 2025-07-12 15.42.04

一方で、以下のように特定の月に絞って検索しようとするとエラーとなり、現時点では絞り込み検索が行えません。

select * from test_table where year=2025 AND month=07;

スクリーンショット 2025-07-21 16.30.01
月毎に絞ってクエリするとエラーになる

それでは Athena 側にパーティションの設定を行い、上記のような絞り込み検索を実行できるようにしてみます。

既存テーブルにパーティションを追加する方法としては、以下ブログで紹介されているような ALTER TABLE ADD PARTITION を用いる手法があります。

https://dev.classmethod.jp/articles/athena-partition-reinvent/#toc-2-s3

しかし現時点では、この手法でパーティション設定を追加しようとしても以下のようにエラーになります。

スクリーンショット 2025-07-21 16.58.29

実行したクエリ
ALTER TABLE test_table ADD PARTITION (year='2025',month='07') location 's3://test-athena-partitioning-0711/2025/07/'
エラー文
FAILED: SemanticException table is not partitioned but partition spec exists: {year=2025, month=07}

上記エラーは、Athena テーブル(本ブログだと test_table)作成時にそもそもパーティション用のカラムが設定されていないために起こります。
詳細は下記 AWS 公式ブログをご参照ください。

SemanticException
...
このエラーは、CREATE TABLE ステートメントでパーティションを定義しなかった場合に発生します。このエラーを解決するには、次のいずれかの操作を行います:
・テーブルを再作成し、PARTIONED BY を使用してパーティションキーを定義します。
・テーブルスキーマを編集します。

https://repost.aws/ja/knowledge-center/athena-failed-semanticexception-table

エラーを解消するにはテーブル再作成が必要ですが、やや面倒なので、今回はテーブルスキーマを編集する方法で解消します。
Athena は、内部的には AWS Glue Data Catalog を使用しているため、Glue コンソールからテーブルスキーマ編集を行います。

Glue コンソールに移動し、ナビゲーションペインから 「Data Catalog tables」 を選択、その後、前項にて作成済みのテーブル test_table を選びます。

スクリーンショット 2025-07-21 17.23.53

テーブルの詳細画面から、Schema タブの 「Edit schema」を選択します。

スクリーンショット 2025-07-21 17.30.43

右上の ADD ボタンを選択。
スクリーンショット 2025-07-21 17.34.11

以下のように year カラムを追加します。「Set as partion key?」のチェックも忘れずに入れます。
スクリーンショット 2025-07-21 17.35.52

month カラムも同様に設定します。
スクリーンショット 2025-07-21 17.40.29

2つ設定したら、右下のボタンから設定を保存します。
スクリーンショット 2025-07-21 17.41.40

そうすると先ほどの ALTER TABLE ADD PARTITION クエリの実行が成功します。
またクエリが成功すると、テーブルの右横にパーティション化済みと表示されていることがわかります。
スクリーンショット 2025-07-21 17.44.01

以上で、パーティション設定はできているはずなので、先ほど失敗した絞り込み検索のクエリを実行してみます。

select * from test_table where year=2025 AND month=07;

今度は成功しました。絞り込みを行ったことでスキャン量が全クエリの時と比較して減少していることがわかります。また、テーブル構造も新たに year と month カラムが設定されており、7月のデータのみクエリできていることがわかります。
スクリーンショット 2025-07-21 17.48.31

ちなみに今の状態では他の月はクエリすることができません。(ALTER TABLE ADD PARTITION を行なっていないため。)
スクリーンショット 2025-07-21 17.55.28
クエリは成功しているが、6月のデータが取得できていない

他の月も絞り込み検索するには、再度パーティションを手動追加する必要があります。

ALTER TABLE test_table ADD PARTITION (year='2025',month='06') location 's3://test-athena-partitioning-0711/2025/06/'

スクリーンショット 2025-07-21 17.57.17

上記設定が終わると、6月のデータも絞り込み検索できるようになります。以上で検証は終わりです。お疲れ様でした〜
スクリーンショット 2025-07-21 17.58.47

終わりに

今回は Athena のパーティションを実際に設定してみました。パーティションに分けることによって、絞り込み検索が可能になり、結果としてスキャン量が減りコストも減るというドキュメントに書かれていることがやっと理解できました。
業務でパーティションという単語が出てくるとよく分からなかったので怖かったのですが、これからは少し勇気を持てそうです。

本ブログが、パーティションについて自分のように初めて触る方の理解の助けになれば幸いです。

参考情報

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/ctas-partitioning-and-bucketing.html
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/ctas-partitioning-and-bucketing-what-is-partitioning.html
https://dev.classmethod.jp/articles/querying-multiple-s3-buckets-with-union/#athena-%25E3%2583%2586%25E3%2583%25BC%25E3%2583%2596%25E3%2583%25AB%25E4%25BD%259C%25E6%2588%2590
https://dev.classmethod.jp/articles/athena-partition-reinvent/#toc-2-s3
https://repost.aws/ja/knowledge-center/athena-failed-semanticexception-table
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/data-sources-glue.html
https://dev.classmethod.jp/articles/tried-to-check-how-to-set-amazon-athena-partition-projection/

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.