AWS SDK for Python (Boto3) で Amazon Athena にクエリする
こんにちは、藤本です。
現地時間 5/19 に Amazon Athena の API が公開され、各種言語の AWS SDK や、AWS CLI でのアクセスもサポートされました。今までプログラムから扱う場合に JDBC しかなかったため、Java 以外の言語でクエリすることができませんでした。(OSS ツールなどでやっている方もいるようですが。)それが AWS SDK を利用するだけで簡単に各種言語のプログラムからアクセスできるようになりました。
Amazon Athena adds API/CLI, AWS SDK support, and audit logging with AWS CloudTrail
弊社ブログエントリでも AWS CLI を利用したクエリの使い方が早速エントリされました。
API や流れは上記エントリを参照してもらうとして、私の方では Boto3 で API をひたすら叩いていきます。
環境
- OS : MacOS 10.12.4
- Python : 3.6.0
- Boto3 : 1.4.4
- Botocore : 1.5.53
- IPython : 6.0.0
※ Boto3 で API を実行していますが、大事なのは Botocore のバージョンです。Amazon Athena の API を叩くためには Botocore のバージョンが1.5.52
以上である必要があります。
$ pip list appnope (0.1.0) boto3 (1.4.4) botocore (1.5.53) decorator (4.0.11) docutils (0.13.1) ipython (6.0.0) ipython-genutils (0.2.0) jedi (0.10.2) jmespath (0.9.2) pexpect (4.2.1) pickleshare (0.7.4) pip (9.0.1) prompt-toolkit (1.0.14) ptyprocess (0.5.1) Pygments (2.2.0) python-dateutil (2.6.0) s3transfer (0.1.10) setuptools (28.8.0) simplegeneric (0.8.1) six (1.10.0) traitlets (4.3.2) wcwidth (0.1.7)
試してみた
それでは早速、Boto3 の関数を叩いて行きましょう。流れは AWS CLI のエントリと同じです。分かりやすく REPL(IPython)でやっていきます。
$ ipython Python 3.6.0 (default, Apr 17 2017, 14:43:12) Type 'copyright', 'credits' or 'license' for more information IPython 6.0.0 -- An enhanced Interactive Python. Type '?' for help. In [1]:
テストデータ準備
今回のテストデータには CloudTrail のログを利用します。CloudTrail のテーブル作成は下記エントリをご参照ください。sdktest
データベースにcloudtrail_logs
テーブルを作成しました。
準備
Athena の Client を呼び出します。AWS CLI の設定ファイルのデフォルトリージョンを ap-northeast-1 にしている方は Athena がリリースされているリージョンをご指定ください。今回はバージニア北部リージョン(us-east-1)を利用します。
In [1]: import boto3 In [2]: athena = boto3.client('athena', region_name='us-east-1')
クエリ実行の開始:start_query_execution
クエリの実行を開始します。クエリはバックグラウンドで実行されるのでこの関数では結果を取得することはできません。返ってくる結果のクエリID を利用して、実行結果を取得します。
Docstring 表示
In [4]: athena.start_query_execution? Signature: athena.start_query_execution(*args, **kwargs) Docstring: .. _Examples and Code Samples: http://docs.aws.amazon.com/athena/latest/ug/code-samples.html Runs (executes) the SQL query statements contained in the ``Query`` string. For code samples using the AWS SDK for Java, see `Examples and Code Samples`_ in the *Amazon Athena User Guide* . See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/StartQu eryExecution>`_ **Request Syntax** :: response = client.start_query_execution( QueryString='string', ClientRequestToken='string', QueryExecutionContext={ 'Database': 'string' }, ResultConfiguration={ 'OutputLocation': 'string', 'EncryptionConfiguration': { 'EncryptionOption': 'SSE_S3'|'SSE_KMS'|'CSE_KMS', 'KmsKey': 'string' } } )
API 実行
データ件数をカウントするクエリを実行します。QueryString に発行する SQL クエリを、QueryExecutionContext に対象のデータベース名を、ResultConfiguration の OutputLocation に結果出力先となる S3 のパスを指定します。
In [12]: athena.start_query_execution( QueryString='select count(*) from cloudtrail_logs', QueryExecutionContext={ 'Database': 'sdktest' }, ResultConfiguration={ 'OutputLocation': 's3:///' } ) Out[13]: {'QueryExecutionId': '092b61a1-c468-4859-9035-39361cc405fc', 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '59', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 03:07:43 GMT', 'x-amzn-requestid': 'fd218080-3f64-11e7-913d-a53b16848cc1'}, 'HTTPStatusCode': 200, 'RequestId': 'fd218080-3f64-11e7-913d-a53b16848cc1', 'RetryAttempts': 0}}
クエリはバックグラウンドで実行されるのですぐに結果が返ってきます。QueryExecutionId
を使って、Athena にクエリの状況や、結果を受け取ることができます。
クエリ実行状況の確認:get-query-execution
バックグラウンドで実行されているクエリの実行状況を確認します。
Docstring 表示
In [14]: athena.get_query_execution? Signature: athena.get_query_execution(*args, **kwargs) Docstring: Returns information about a single execution of a query. Each time a query executes, information ab out the query execution is saved with a unique ID. See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/GetQueryExecution>`_ **Request Syntax** :: response = client.get_query_execution( QueryExecutionId='string' )
API 実行
先ほど実行したクエリの実行状況を確認します。QueryExecutionId
にクエリ実行のレスポンスに含まれるQueryExecutionId
の値を指定します。
In [15]: athena.get_query_execution( QueryExecutionId='092b61a1-c468-4859-9035-39361cc405fc' ) Out[15]: {'QueryExecution': {'Query': 'select count(*) from cloudtrail_logs', 'QueryExecutionContext': {'Database': 'sdktest'}, 'QueryExecutionId': '092b61a1-c468-4859-9035-39361cc405fc', 'ResultConfiguration': {'OutputLocation': 's3:///092b61a1-c468-4859-9035-39361cc405fc.csv'}, 'Statistics': {'DataScannedInBytes': 94623484, 'EngineExecutionTimeInMillis': 8794}, 'Status': {'CompletionDateTime': datetime.datetime(2017, 5, 23, 12, 7, 52, 601000, tzinfo=tzlocal()), 'State': 'SUCCEEDED', 'SubmissionDateTime': datetime.datetime(2017, 5, 23, 12, 7, 43, 472000, tzinfo=tzlocal())}}, 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '1063', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 03:08:01 GMT', 'x-amzn-requestid': '07f5ded6-3f65-11e7-b0f2-a33e056554a8'}, 'HTTPStatusCode': 200, 'RequestId': '07f5ded6-3f65-11e7-b0f2-a33e056554a8', 'RetryAttempts': 0}}
State
にクエリのステータスや、ResultConfiguration
にクエリ結果の CSV ファイルの出力パスが返ってきます。
クエリ実行結果の取得:get-query-results
クエリの実行結果を取得します。上記結果のState
がSUCCEEDED
の時にクエリの結果を取得することができます。
Docstring 表示
In [21]: athena.get_query_results? Signature: athena.get_query_results(*args, **kwargs) Docstring: Returns the results of a single query execution specified by ``QueryExecutionId`` . This request does not execute the query but returns results. Use StartQueryExecution to run a query. See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/GetQueryResults>`_ **Request Syntax** :: response = client.get_query_results( QueryExecutionId='string', NextToken='string', MaxResults=123 )
API 実行
先ほど実行したクエリの実行結果を取得します。QueryExecutionId
にクエリ実行のレスポンスに含まれるQueryExecutionId
の値を指定します。
In [22]: athena.get_query_results( QueryExecutionId='092b61a1-c468-4859-9035-39361cc405fc' ) Out[22]: {'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '574', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 04:57:28 GMT', 'x-amzn-requestid': '523b176c-3f74-11e7-b4ae-9b1216f5a3f4'}, 'HTTPStatusCode': 200, 'RequestId': '523b176c-3f74-11e7-b4ae-9b1216f5a3f4', 'RetryAttempts': 0}, 'ResultSet': {'ResultSetMetadata': {'ColumnInfo': [{'CaseSensitive': False, 'CatalogName': 'hive', 'Label': '_col0', 'Name': '_col0', 'Nullable': 'UNKNOWN', 'Precision': 19, 'Scale': 0, 'SchemaName': '', 'TableName': '', 'Type': 'bigint'}]}, 'Rows': [{'Data': [{'VarCharValue': '_col0'}]}, {'Data': [{'VarCharValue': '370889'}]}]}}
ResultSet
に結果が記載されています。今回はレコード件数が 370,889 件あるということを取得できました。
実行クエリの中断:stop-query-execution
バックグラウンドしているクエリを中断します。
Docstring 表示
Signature: athena.stop_query_execution(*args, **kwargs) Docstring: .. _Examples and Code Samples: http://docs.aws.amazon.com/athena/latest/ug/code-samples.html Stops a query execution. For code samples using the AWS SDK for Java, see `Examples and Code Samples`_ in the *Amazon Athena User Guide* . See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/StopQueryExecution>`_ **Request Syntax** :: response = client.stop_query_execution( QueryExecutionId='string' )
API実行
State が RUUNING のクエリに対して、実行することで実行中のクエリを中断します。
### State が RUNNING のクエリに対して In [49]: athena.get_query_execution( QueryExecutionId=result['QueryExecutionId'] ) Out[49]: {'QueryExecution': {'Query': 'select count(*) from cloudtrail_logs', 'QueryExecutionContext': {'Database': 'sdktest'}, 'QueryExecutionId': '7c30fd12-1326-46da-bfca-b3092dc3517c', 'ResultConfiguration': {'OutputLocation': 's3:///7c30fd12-1326-46da-bfca-b3092dc3517c.csv'}, 'Statistics': {}, 'Status': {'State': 'RUNNING', 'SubmissionDateTime': datetime.datetime(2017, 5, 23, 14, 33, 23, 282000, tzinfo=tzlocal())}}, 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '784', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 05:33:23 GMT', 'x-amzn-requestid': '56a6e3a6-3f79-11e7-9fdf-9d7f8fc70550'}, 'HTTPStatusCode': 200, 'RequestId': '56a6e3a6-3f79-11e7-9fdf-9d7f8fc70550', 'RetryAttempts': 0}} ### Stop API を実行すると In [50]: athena.stop_query_execution( QueryExecutionId=result['QueryExecutionId'] ) Out[50]: {'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '2', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 05:33:24 GMT', 'x-amzn-requestid': '572c40ac-3f79-11e7-b4ae-9b1216f5a3f4'}, 'HTTPStatusCode': 200, 'RequestId': '572c40ac-3f79-11e7-b4ae-9b1216f5a3f4', 'RetryAttempts': 0}} ### CANCELLED になる In [50]: athena.get_query_execution( QueryExecutionId=result['QueryExecutionId'] ) Out[52]: {'QueryExecution': {'Query': 'select count(*) from cloudtrail_logs', 'QueryExecutionContext': {'Database': 'sdktest'}, 'QueryExecutionId': '7c30fd12-1326-46da-bfca-b3092dc3517c', 'ResultConfiguration': {'OutputLocation': 's3:///7c30fd12-1326-46da-bfca-b3092dc3517c.csv'}, 'Statistics': {'DataScannedInBytes': 5903681, 'EngineExecutionTimeInMillis': 1071}, 'Status': {'CompletionDateTime': datetime.datetime(2017, 5, 23, 14, 33, 24, 426000, tzinfo=tzlocal()), 'State': 'CANCELLED', 'SubmissionDateTime': datetime.datetime(2017, 5, 23, 14, 33, 23, 282000, tzinfo=tzlocal())}}, 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '1058', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 05:33:43 GMT', 'x-amzn-requestid': '62e02a0a-3f79-11e7-b2a1-1fc3451d9eb1'}, 'HTTPStatusCode': 200, 'RequestId': '62e02a0a-3f79-11e7-b2a1-1fc3451d9eb1', 'RetryAttempts': 0}}
実行したクエリ一覧の取得:list-query-executions
実行中、実行済みのクエリ ID を一覧で取得します。クエリ ID しか取得しないので詳細は get-query-execution で取得する必要があります。
Docstring 表示
Signature: athena.list_query_executions(*args, **kwargs) Docstring: .. _Examples and Code Samples: http://docs.aws.amazon.com/athena/latest/ug/code-samples.html Provides a list of all available query execution IDs. For code samples using the AWS SDK for Java, see `Examples and Code Samples`_ in the *Amazon Athena User Guide* . See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/ListQueryExecutions>`_ **Request Syntax** :: response = client.list_query_executions( NextToken='string', MaxResults=123 )
API 実行
全ての API 実行履歴を取得します。
In [57]: athena.list_query_executions() Out[57]: {'NextToken': 'eJxVzMEKAiEUQNF/cWvCPHXeaLtpRqJlRB8g6sJFGo7CSPTvBa3aXg73RZ4lPmzp5Eii3+m1hdLNHlyrMSeTaqydnkP979upz87llurFUyFBS9TTCEqRA9mCy8n/jiAVTnriXCFX9HZfFmNWs1LUeuAII8MAgknwjn0FZ2BRWO+lGyyS9wcxMy//', 'QueryExecutionIds': ['7c30fd12-1326-46da-bfca-b3092dc3517c', '86c223cb-1d40-4d43-b6e8-9c093d2071a5', '5e9ef952-791d-4a75-b11d-b86e9315e608', '5d114c8e-8b8e-4bf6-8f95-b68658defa19', '3c1fdcc7-d87e-4960-bcb6-65e00212120b', 'a9543896-e423-4520-a5ae-196047e57636', '51ab1316-3b79-40c6-a4d3-065db5ff05a8', '5c538d07-2625-4f48-aaee-4b3413d8414e', '471e8383-c5fb-4d38-ac00-3fbc8249ce59', '69902615-6e13-41dc-8622-1a63add4c0a6'], 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '2172', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 05:52:16 GMT', 'x-amzn-requestid': 'fa2252e0-3f7b-11e7-b03f-edb3a58fd066'}, 'HTTPStatusCode': 200, 'RequestId': 'fa2252e0-3f7b-11e7-b03f-edb3a58fd066', 'RetryAttempts': 0}}
クエリ実行状況の一括取得:batch-get-query-execution
クエリ実行状況は一括取得することができます。
Docstring 表示
Signature: athena.batch_get_query_execution(*args, **kwargs) Docstring: Returns the details of a single query execution or a list of up to 50 query executions, which you provide as an array of query execution ID strings. To get a list of query execution IDs, use ListQueryExecutions . Query executions are different from named (saved) queries. Use BatchGetNamedQuery to get details about named queries. See also: `AWS API Documentation <https://docs.aws.amazon.com/goto/WebAPI/athena-2017-05-18/BatchGetQueryExecution>`_ **Request Syntax** :: response = client.batch_get_query_execution( QueryExecutionIds=[ 'string', ] )
get-query-execution
と比べて、QueryExecutionIds
でクエリ ID を list で指定できるようになっただけですね。
API 実行
In [72]: athena.batch_get_query_execution( QueryExecutionIds=[ '3c1fdcc7-d87e-4960-bcb6-65e00212120b', '092b61a1-c468-4859-9035-39361cc405fc' ] ) Out[72]: {'QueryExecutions': [{'Query': 'select count(*) from cloudtrail_logs', 'QueryExecutionContext': {'Database': 'sdktest'}, 'QueryExecutionId': '092b61a1-c468-4859-9035-39361cc405fc', 'ResultConfiguration': {'OutputLocation': 's3:///092b61a1-c468-4859-9035-39361cc405fc.csv'}, 'Statistics': {'DataScannedInBytes': 94623484, 'EngineExecutionTimeInMillis': 8794}, 'Status': {'CompletionDateTime': datetime.datetime(2017, 5, 23, 12, 7, 52, 601000, tzinfo=tzlocal()), 'State': 'SUCCEEDED', 'SubmissionDateTime': datetime.datetime(2017, 5, 23, 12, 7, 43, 472000, tzinfo=tzlocal())}}, {'Query': 'select count(*) from cloudtrail_logs', 'QueryExecutionContext': {'Database': 'sdktest'}, 'QueryExecutionId': '3c1fdcc7-d87e-4960-bcb6-65e00212120b', 'ResultConfiguration': {'OutputLocation': 's3:///3c1fdcc7-d87e-4960-bcb6-65e00212120b.csv'}, 'Statistics': {'DataScannedInBytes': 95200201, 'EngineExecutionTimeInMillis': 11393}, 'Status': {'CompletionDateTime': datetime.datetime(2017, 5, 23, 14, 30, 49, 342000, tzinfo=tzlocal()), 'State': 'SUCCEEDED', 'SubmissionDateTime': datetime.datetime(2017, 5, 23, 14, 30, 37, 623000, tzinfo=tzlocal())}}], 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive', 'content-length': '1012', 'content-type': 'application/x-amz-json-1.1', 'date': 'Tue, 23 May 2017 07:09:16 GMT', 'x-amzn-requestid': 'bc5e3e88-3f86-11e7-b537-57c69699542d'}, 'HTTPStatusCode': 200, 'RequestId': 'bc5e3e88-3f86-11e7-b537-57c69699542d', 'RetryAttempts': 0}, 'UnprocessedQueryExecutionIds': []}
QueryExcecutions
に配列でそれぞれのクエリ実行状況が含まれています。
まとめ
いかがでしたでしょうか? Python プログラムから Athena へクエリしたくて、標準 SDK の登場を待望んだ方も多くいらっしゃるのではないでしょうか。AWS SDK for Python(Boto3)を利用することで Amazon Athena へ簡単にクエリすることができるようになりました。