ちょっと話題の記事

[新機能]Amazon Athena ルールベースでパーティションプルーニングを自動化する Partition Projection の徹底解説

2020.06.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Partition Projection(パーティション射影)は、テーブル定義で指定したパーティションキーのルールやフォーマットからパーティションを計算し、パーティションプルーニングを自動化します。パフォーマンスの向上やパーティション管理の自動化などインパクトがある新機能なので、実際の動作を確認しつつ、ユースケースについて解説します。

用語の補足:パーティションプルーニングとは、一定の期間(年、月、日)やキー情報に基づき、データを分割管理したデータをクエリする際に、範囲外のデータスキャンを避ける仕組みを表します。

Glueパーティションの課題

従来のGlueパーティションは、メタデータストアがパーティション情報を保持しているので、データストア(S3)をスキャンすることなく、メタデータストアの情報のみを用いてパーティションプルーニングできます。一般的なユースケースにおいてはこの方式が優れています。しかし、メタデータストアのパーティション追加の手間や、非常に多くのパーティションが存在するユースケースではデータカタログ(Glue Data Catalog)に対するパーティション取得API(GetPartitions)の呼び出しがクエリパフォーマンスのボトルネックになる場合がありました。

Partition Projectionによるパーティション取得

そこで、登場したのが、Partition Projectionです。

Partition Projectionを用いると、非常に多くのパーティションがあるテーブルに対するクエリを高速化するとともに、パーティション管理を自動化します。パーティションを計算するために必要な情報は、Partition Projection設定によって、Athenaに与えられます。

Partition Projectionでは、パーティションをデータカタログ(Glue Data Catalog)に対するパーティション取得API(GetPartitions)呼び出しすることなく、設定から計算します。多くの場合、インメモリオペレーションはリモートオペレーションよりも高速であるため、Partition Projectionを用いると、非常に多くのパーティションを持つテーブルに対するクエリの実行時間が短縮できます。クエリとデータの特性によっては、パーティションメタデータの取得待ちが軽減され、クエリの実行時間が短縮されます。

Projection可能なパーティション構造

Partition Projectionは、パーティションが次のような型に設定できます。詳細は、パーティション射影のサポートされている型をご覧ください。

  • 整数(integer)
    • [1, 2, 3, 4, ..., 1000][0500, 0550, 0600, ..., 2500] などの整数の連続シーケンス
  • 日付(date)
    • [20200101, 20200102, ..., 20201231][1-1-2020 00:00:00, 1-1-2020 01:00:00, ..., 12-31-2020 23:00:00] など、日付または日時の連続シーケンス
  • 列挙値(enum)
    • 空港コードや AWS リージョンなど、列挙値の有限セット
  • 挿入型(injected)
    • 使用できる値をいくつかの論理範囲内で手動で生成することができないが、クエリの WHERE 句で単一の値として指定されるパーティション列には、挿入型を使用する

Partition Projectionは、上記のルールに基づきパーティションが存在する想定で動作します。例えば、型にdateを指定して、「2010年から2020年まで日毎」に設定すると、Athenaが約3650パーティションを計算して動作します。

Partition Projectionの検証

サンプルデータ

データレイクで最もよく利用されるパターンは、時系列データの保存です。今回は、検証用にサンプルデータlineorderを、1992/01/01から1998/08/02まで、年月日でパーティションしたデータを用意しました。以降では、このデータに対して、Partition Projectionを設定します。

テーブル定義

Partition Projectionは、今回は年月日をまとめて定義しました。このキーには例えば1992/01/01のような文字列が入ります。

PARTITIONED BY ( 
  `orderdate` string)

Partition Projectionの設定は、TBLPROPERTIESに指定します。以下、TBLPROPERTIESの抜粋です。パーティションキーorderdateに対する設定なので、projection.orderdate.〜と指定しています。

TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.orderdate.type' = 'date',
  'projection.orderdate.range' = '1992/01/01,NOW',
  'projection.orderdate.format' = 'yyyy/MM/dd',
  'projection.orderdate.interval' = '1',
  'projection.orderdate.interval.unit' = 'DAYS',
  'storage.location.template' = 's3://<bucket_name>/ssbgz/lineorder-partitioned-daily/${orderdate}',
  :
  :
  • projection.enabledは、Partition Projectionを有効(true)に設定
  • projection.orderdate.typeは、1992/01/01から現在(NOW)までを指定
  • projection.orderdate.formatは、スラッシュ区切りの年月日を指定
  • projection.orderdate.intervalは、毎日なので1を指定
  • projection.orderdate.interval.unitは、単位は日(DAYS
  • storage.location.templateは、S3のパスを指定します。

実際のDDLは以下の通りです。

CREATE EXTERNAL TABLE `lineorder_pp`(
  lo_orderkey        bigint, 
  lo_linenumber      bigint, 
  lo_custkey         bigint, 
  lo_partkey         bigint, 
  lo_suppkey         bigint, 
  lo_orderdate       string, 
  lo_orderpriority   string, 
  lo_shippriority    bigint, 
  lo_quantity        bigint, 
  lo_extendedprice   bigint, 
  lo_ordertotalprice bigint, 
  lo_discount        bigint, 
  lo_revenue         bigint, 
  lo_supplycost      bigint, 
  lo_tax             bigint, 
  lo_commitdate      string, 
  lo_shipmode        string)
PARTITIONED BY ( 
  `orderdate` string)
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY '|' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://<bucket_name>/ssbgz/lineorder-partitioned-daily/'
TBLPROPERTIES (
  'projection.enabled' = 'true',
  'projection.orderdate.type' = 'date',
  'projection.orderdate.range' = '1992/01/01,NOW',
  'projection.orderdate.format' = 'yyyy/MM/dd',
  'projection.orderdate.interval' = '1',
  'projection.orderdate.interval.unit' = 'DAYS',
  'storage.location.template' = 's3://<bucket_name>/ssbgz/lineorder-partitioned-daily/${orderdate}',
  'classification'='csv', 
  'compressionType'='gzip', 
  'delimiter'='|', 
  'typeOfData'='file')

クエリの実行

上記のDDLでテーブルを作成した後、パーティション設定は一切行なっていませんが、パーティションが自動認識されています。

Glueパーティションと実行時間の比較

全く同じデータに対して、Glueパーティションのテーブルを作成しました。先程のPartition Projection設定したテーブルとこのテーブル間で比較しました。2406パーティションなので、「非常に多くのパーティション」というほどではありませんでしたが、先程のPartition Projection設定したテーブルの方が1.09秒から0.55秒へパフォーマンスの改善が見られました。恐らく、パーティション数の増加に伴い、パフォーマンスの改善は顕著に現れると考えられます。

ユースケース

Partition Projectionを用いたときのパフォーマンスの向上やパーティション管理の自動化などを鑑みると、一見、GlueパーティションよりもPartition Projectionのパーティションの方が優れているように思われがちですが、ユースケースに応じて一長一短があります。

Partition Projectionのパーティションが向いているユースケース

  • 非常に多くのパーティションがあるテーブルに対するクエリが思ったほどすぐに完了しない場合
  • データに新しいパーティションが作成されたとき、定期的にパーティションをテーブルに追加している場合
  • 非常に多くのパーティション化されたデータがS3に保存されていて、メタデータストアで管理 するのが現実的でなく、クエリで参照する対象のデータがほんの一部の場合

Glueパーティションの方が向いているユースケース

  • Redshift Spectrum、Glue、EMRなど、別のサービスを通じて同じテーブルを参照する場合
    • Partition Projectionは、Athenaのクエリエンジンのみサポートする機能なので、別のクエリエンジンは、パーティションが登録されていないためデータが参照できません
  • パーティションキーの半分以上連続しない場合
    • Glueパーティションはデータが存在するパーティションをピンポイントで設定できます
  • Partition Projectionが予測可能なパターンに一致できない場合
    • Partition Projectionの型(integer、date、enum、injected)を利用できない場合
    • storage.location.templateが一意に指定できない場合

考慮事項と制約事項

  • Partition Projectionを有効にすると、パーティションを設定する必要がありませんが、パーティションメタデータを無視します
  • Partition Projectionで計算されたパーティションが S3に存在しない場合も、Athenaはそのパーティションが存在するように動作します
    • ただし、空のパーティションが多すぎる場合、従来の AWS Glue パーティションに比べてパフォーマンスが低下する可能性があります
    • 射影パーティションの半分以上が空の場合は、従来のGlueパーティションを使用することをお勧めします
  • Partition Projectionは、Athena を通じてテーブルがクエリされた場合にのみ使用できます
    • Amazon Redshift Spectrum または Amazon EMR などの別のサービスを通じて同じテーブルが読み取られた場合、標準パーティションメタデータが使用されます
  • Partition Projectionは DML 専用機能であるため、Athena により射影されますが AWS Glue カタログまたは外部 Hive メタストアに登録されていないパーティションは SHOW PARTITIONS によりリストされません
  • Athena のビューは、Partition Projectionの設定プロパティを使用しません

最後に

従来、ELB(CLB、ALB)やCloudtrailのログのようにS3への出力パスが決まっているログファイルのパーティション設定するには、テーブル定義の他に別途パーティション設定が必要でしたが、Partition Projectionを用いることでテーブル定義するだけでクエリを実行できるようになります。

Partition Projectionは、パフォーマンスの向上やパーティション管理の自動化などインパクトがある新機能ですが、あくまでもAmazon Athenaのクエリエンジン専用の機能です。サーバレスアナリティクスのクエリエンジンとして、Amazon Athena一択であれば、Partition Projectionは非常に有効です。一方、Glueデータカタログを用いて、他のサービス(Amazon Redshift Spectrum、Amazon EMR、AWS Glue)とS3データレイクを共有するユースケースでは、従来通り、Glueパーティションを優先することになります。

AWSJの川村さんが、最新(2020/06/17)のAWS Black Belt Online Seminer Amazon Athenaで解説していますので、こちらもぜひご覧ください。Partition Projectionの解説動画はここからです。

合わせて読みたい