AthenaのSaved Queriesをコンソール以外から取得する


はじめに

AWSアカウントをクローズする際にAthenaのバックアップを行ったのがきっかけです。
コンソール上でSaved Queriesをまとめて取得する方法が見つからず、またS3に保存されているわけでも無さそうだったため、備忘録として試した内容を以下にまとめます。

Saved Queries

何度も使うクエリに名前と説明を付けて保存しておく機能です。
ワークグループごとに分けて保存できます。

取得方法

以下の2つの方法でSaved Queriesを取得します。

  • AWS CLI
  • AWS SDK for Python

実行環境

  • macOS High Sierra 10.13.6
  • aws-cli 1.16.128
  • Python 3.6.8
  • botocore 1.15.46

~/.aws/credentialsにprofileの設定がされていることが前提です。

AWS CLIを使う方法

公式のドキュメントを参考にしました。

クエリのIDリスト取得

コンソール上からは分かりませんが、各クエリにはIDが付与されています。
クエリを取得するにはこのIDが必要なため、まずはlist-named-queriesコマンドを使ってIDのリストを取得します。

コマンド
aws athena list-named-queries --work-group primary --profile default
実行結果
{
    "NamedQueryIds": [
        "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    ]
}

クエリの取得

get-named-queryコマンドでIDを指定してクエリを取得します。

コマンド
aws athena get-named-query --named-query-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --profile default
実行結果
{
    "NamedQuery": {
        "Name": "test query",
        "Description": "test saved query",
        "Database": "test_database",
        "QueryString": "SELECT * FROM \"test_database\".\"test_table\" limit 10",
        "NamedQueryId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "WorkGroup": "primary"
    }
}

一度に複数のクエリを取得することはできないため、全てのクエリを取得するにはIDの数だけコマンドを実行する必要があります。

AWS SDK for Python (boto3)を使う方法

基本的な流れはAWS CLIの場合と同じです。
Boto3のドキュメントを参考にしました。

クエリのIDリスト取得

list_named_queries関数でIDリストを取得します。

import os
import json
import boto3
import time

from boto3.session import Session
profile = 'default'
session = Session(profile_name=profile)
athena = session.client('athena','ap-northeast-1')

#IDのリスト取得
saved_query_list = athena.list_named_queries(
    WorkGroup='primary',
    MaxResults=50
)

レスポンスの内容について

基本的ににはAWS CLIと同様のJSON形式で返却されます。

レスポンス形式
{
    'NamedQueryIds': [
        'string',
    ],
    'NextToken': 'string'
}

AWS CLIの場合との違いはNextTokenです。
AWS SDKで一度に取得できるIDの数はリクエストで指定したMaxResultsの値(最大50)となり、保存されているクエリの数がそれより多い場合はレスポンスにNextTokenがセットされています。

IDリストの続きを取得

51個目以降(リクエストでMaxResults=50を設定した場合)のIDリストを取得するには、NextTokenを設定して再度リクエストを行います。

next_saved_query_list = athena.list_named_queries(
    WorkGroup='primary',
    MaxResults=50,
    NextToken=saved_query_list['NextToken']
)

更にIDリストが続く場合は同様のリクエストを繰り返します。

クエリの取得

get_named_query関数にIDを指定してクエリを取得します。

saved_query = athena.get_named_query(
    NamedQueryId=saved_query_list['NamedQueryIds'][0]
)

AWS CLIの場合と同様の形式でクエリが返却されます。

レスポンス形式
{
    'NamedQuery': {
        'Name': 'string',
        'Description': 'string',
        'Database': 'string',
        'QueryString': 'string',
        'NamedQueryId': 'string',
        'WorkGroup': 'string'
    }
}

全てのクエリを取得するにはIDの数だけget_named_query関数を実行します。

全てのクエリを取得

IDリストの取得、クエリの取得、保存を行うコードをまとめてみました。
ローカルディレクトリにクエリ毎にファイルを分けて保存しています。

import os
import json
import boto3
import time
from boto3.session import Session

profile = 'default'
session = Session(profile_name=profile)
athena = session.client('athena','ap-northeast-1')

# IDリスト取得
query_id_list = []
nextToken = ''
while True:
    if nextToken == '':
        saved_query_list = athena.list_named_queries(
            WorkGroup='primary',
            MaxResults=50
        )
    else:
        saved_query_list = athena.list_named_queries(
            WorkGroup='primary',
            MaxResults=50,
            NextToken=nextToken
        )

    tmp_query_id_list = saved_query_list['NamedQueryIds']
    for query_id in tmp_query_id_list:
        query_id_list.append(query_id)

    if 'NextToken' in saved_query_list.keys():    #50件以上ある場合
        nextToken = saved_query_list['NextToken']
        time.sleep(1)
    else:
        nextToken=''
        break

print('query num:',len(query_id_list))

# クエリ取得&保存
for query_id in query_id_list:
    filename = './query/' + query_id + '.json'
    # 取得
    query = athena.get_named_query(
        NamedQueryId=query_id
    )
    # 保存
    with open(filename, mode='w') as outfile:
        outfile.write(json.dumps(query))    
    time.sleep(1)

今回は試していませんが、create_named_query関数を使えば別のワークグループやAWSアカウントへのクエリの保存もできると思います。

まとめ

AWS CLIを使う方法とAWS SDKを使う方法の2つを試しました。
どちらも方法もIDリストの取得 → クエリの取得という手順を踏む必要があります。
まとめて取得したい場合や、シェルを書くことに抵抗が無い人以外はSDKを使って作業するのが良いと思います。