Why Nostr? What is Njump?
2024-06-17 08:13:16

DevelopersIO RSS feed【非公式】 on Nostr: ...

【AthenaのクエリでWHERE句に関数を利用してもパーティションを効率よく走査してくれるか確認してみた】
CX事業本部@大阪の岩田です。 年(year)と月(month)にパーティションが切られたAthenaのテーブルに対して直近1週間のデータを集計するクエリを書く機会がありました。直近1週間ということで月跨ぎのケースを考慮して最初は以下のようにWHERE句を書いていました。 しかし、WHERE句の条件が増えてくると最初にパーティションを絞り込む部分がゴチャゴチャしてくるのが気になり以下のような書き換えを検討しました。 ここで1つの疑問が浮かびました。 パーティションが設定されたカラムに対してCONCAT等の関数を適用した場合でもAtehanaのクエリエンジンは当該パーティションだけを効率よく走査してくれるのでしょうか?一応prestroについて調べると以下の情報がヒットしたのでAthenaでもパーティションを考慮していい感じにフィルタしてくれそうではあります。 ということで実際にいくつかのクエリを実行しながら確認してみました。 環境 今回利用した環境です Athena engine version 3 パーティション管理: Glue Data Catalog 以前こちらのLTで利用したSlackの投稿を分析対象としてSQLを発行していきます Glueのマネコンから確認できるテーブルのパーティションは以下の通りでした やってみる ここから色々なEXPLAIN ANALYZEを付けながら色々なSQLを実行し、出力を確認していきます。 とりあえず全件スキャン まずは全件スキャン時の実行計画を確認しておきます。本来は「Athena破産」のリスクがあるので避けるべきSQLですが、まあ対したデータ量じゃないことが分かっているので気にせずスキャンしちゃいます。 実行結果です 21.17MBのデータをスキャンしていることが分かります。 yearとmonthを1つずつ条件指定 続いて2019年12月と2020年1月のデータを対象に絞り込んでみます。この際year=...month=...といった具合に特に関数は使わず地道に1つづつ条件を指定していきます。 実行結果です スキャン対象が4.84MBに減少し、以下の出力の通りアクセス対象のパーティションが絞られていることが分かります CONCATとBETWEENで範囲を指定してみる 続いてCONCATとBETWENNを使って日付=パーティションの範囲を指定してみます。 実行結果です 先ほどと同様スキャン対象は4.84MBでした。CONCATを使っても問題なくパーティションを有効活用できてそうですね date_parseしてみる せっかくなのでもう少し試してみます。yearとmonthをdate_parseしてvarcharからtimestamp型にCASTするとどうでしょうか? 実行結果です こちらも問題なくパーティションを有効活用できています。 RANDOM()と組み合わせてみる 先ほどまではmonthが01のレコードを対象としていましたが、RANDOM()を使って求めたmonth + 1~10の整数が12になるレコードを対象として抽出してみます 実行結果です 今度はyear=2019のかつmonthが1~12の合計12パーティションにアクセスしていることが分かります。スキャン量も14.36MBに増えています。RANDOM()の結果が確定しないとどのパーティションを読み込むべきかAthenaのエンジンからは判断できないのでこれは妥当な動きでしょう。 まとめ Athenaでクエリを実行する際WHERE句に関数を使ってもいい感じにパーティションを使ってくれることを確認しました。ちゃんとオプティマイザが最適化してくれることが分かって一安心です。とはいえあまり複雑なことをし過ぎると意図通りのアクセスパスにならない可能性もあるので、実際にクエリを書く際は「Athena破産」することが無いようにしっかりEXPLAIN ANALYZEの結果を確認しながらクエリを構築していきましょう。
https://dev.classmethod.jp/articles/athena-use-partition-when-use-function-in-where-clause/
Author Public Key
npub16u6jx85wavk5n0kw5r46ma7dunupsp7acmtn3xys7keqvlsfjxpsar5q5c