Amazon Athena でクエリ実行計画の可視化と、実行結果の統計情報を取得出来るようになりました

2022.07.22

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

いわさです。

Amazon Athena では1年前のアップデートでクエリパフォーマンスを改善するための実行計画を利用することが出来るようになりました。

そして、本日のアップデートで実行計画の可視化機能が提供され、さらに実行済みクエリから統計情報が取得出来るようになりました。

この記事では、以下のような料金情報CSVを集計するクエリを例にご紹介したいと思います。

実行計画の可視化

以前から、EXPLAIN を実行する機能は Athena でも可能で、以下のような情報を出力することが出来ていました。
しかし、結果の解析に少しコツで、可視化など行いたい場合は別のツールを使って可視化する必要がありました。

今回のアップデートで、実行ボタンの隣に「説明」ボタンが追加されています。
こちらはクエリ実行前に操作することが可能で、押下すると EXPLAIN を可視化する画面へ遷移し、入力中のクエリに対して EXPLAIN 実行した上で可視化まで行ってくれます。

「説明」画面では、分散プランと論理プランの2つのタブが用意されています。

それぞれの実行計画内容を理解するにあたっては以下のドキュメントをご参照ください。

分散プラン

分散プランでは処理ステージごとのノード内容を確認することが可能です。

上記可視化内容の表示時に、裏では以下のクエリが実行されています。

分散プラン選択時

EXPLAIN (FORMAT JSON, TYPE DISTRIBUTED) select
    month as hoge,
    sum(cast(cost as double)) as monthcost
from iwasacost
where month >= '2022-04'
group by month
order by month

論理プラン

こちらは LOGICALタイプの EXPLAIN 結果となっています。

上記可視化内容の表示時に、裏では以下のクエリが実行されています。

論理プラン選択時

EXPLAIN (FORMAT JSON, TYPE LOGICAL) select
    month as hoge,
    sum(cast(cost as double)) as monthcost
from iwasacost
where month >= '2022-04'
group by month
order by month

どちらのプランでもエクスポートが可能で、画像(SVG, PNG)あるいは JSON 形式で出力することが出来ます。
JSONの場合は以下の形式で取得することが出来ます。

{
  "id" : "11",
  "name" : "Output",
  "identifier" : "[month, monthcost]",
  "details" : "monthcost := sum\n",
  "children" : [ {
    "id" : "250",
    "name" : "RemoteMerge",
    "identifier" : "[month ASC_NULLS_LAST]",
    "details" : "",
    "children" : [ {
      "id" : "294",
      "name" : "LocalMerge",
      "identifier" : "[month ASC_NULLS_LAST]",
      "details" : "",
      "children" : [ {
        "id" : "251",
        "name" : "PartialSort",
        "identifier" : "[month ASC_NULLS_LAST]",
        "details" : "",
        "children" : [ {
          "id" : "249",
          "name" : "RemoteExchange",
          "identifier" : "[REPARTITION]",
          "details" : "",
          "children" : [ {
            "id" : "333",
            "name" : "Project",
            "identifier" : "[]",
            "details" : "",
            "children" : [ {
              "id" : "4",
              "name" : "Aggregate(FINAL)[month][$hashvalue]",
              "identifier" : "",
              "details" : "sum := \"sum\"(\"sum_9\")\n",
              "children" : [ {
                "id" : "310",
                "name" : "LocalExchange",
                "identifier" : "[HASH][$hashvalue] (\"month\")",
                "details" : "",
                "children" : [ {
                  "id" : "316",
                  "name" : "RemoteExchange",
                  "identifier" : "[REPARTITION][$hashvalue_10]",
                  "details" : "",
                  "children" : [ {
                    "id" : "314",
                    "name" : "Aggregate(PARTIAL)[month][$hashvalue_11]",
                    "identifier" : "",
                    "details" : "sum_9 := \"sum\"(\"expr\")\n",
                    "children" : [ {
                      "id" : "2",
                      "name" : "ScanFilterProject",
                      "identifier" : "[table = awsdatacatalog:HiveTableHandle{schemaName=iwasacost, tableName=iwasacost, analyzePartitionValues=Optional.empty}, filterPredicate = (\"month\" >= CAST('2022-04' AS varchar))]",
                      "details" : "expr := CAST(\"cost\" AS double)\n$hashvalue_11 := \"combine_hash\"(bigint '0', COALESCE(\"$operator$hash_code\"(\"month\"), 0))\nLAYOUT: iwasacost.iwasacost\ncost := cost:string:15:REGULAR\nmonth := month:string:1:REGULAR\n",
                      "children" : [ ],
                      "remoteSources" : [ ]
                    } ],
                    "remoteSources" : [ ]
                  } ],
                  "remoteSources" : [ ]
                } ],
                "remoteSources" : [ ]
              } ],
              "remoteSources" : [ ]
            } ],
            "remoteSources" : [ ]
          } ],
          "remoteSources" : [ ]
        } ],
        "remoteSources" : [ ]
      } ],
      "remoteSources" : [ ]
    } ],
    "remoteSources" : [ ]
  } ],
  "remoteSources" : [ ]
}

上記のように可視化はされますが、中身としては表示の際に EXPLAIN が実行されています。
そのため、Athena のデータスキャン料金は発生しませんが、Glue メタデータの取得に関する料金が発生する場合がある点は従来の EXPLAIN 利用時と同等ですのでご注意ください。

実行結果の統計情報

こちらは新しい機能で、実行結果から実際の統計情報を取得することが出来ます。
前述の実行計画と照らし合わせることで、パフォーマンスの測定結果から洞察を得ることが出来ます。

使い方ですが、新たにクエリ結果の隣に「クエリの統計」タブが追加されていますのでそちらを表示し、「実行の詳細」ボタンを押下します。

先程と同様に別タブで実行の詳細情報が表示され、以下のように実行ステージごとに細分化された統計情報を取得することが出来ます。

こちらの可視化機能ですが、裏側では今回新たに追加された Athena API のGetQueryRuntimeStatistics が実行されています。

こちらは、Athena のクエリ実行キューがキャンセルされていたり、実行中の場合は取得が出来ません。成功あるいは失敗している必要があります。

なお、本日時点では AWS CLI だと V1 でのみ利用が可能でした。
v1.25.35から利用出来ます。

さいごに

本日は、Amazon Athena でクエリ実行計画の可視化と、実行結果の統計情報を取得が出来るようになったので使用方法などをご紹介しました。
実行計画が見やすくなり、またステージベースでのパフォーマンス情報を取得出来るようになったので、こちらを使ってクエリチューニングを是非行ってみてください。