6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【AWS Athena】クエリ実行結果を高速に取得する v2【Python】

Last updated at Posted at 2021-11-26

はじめに

Python3上でSQLを書き、awswranglerを使用してデータを取得する方法を紹介します。
タイトルの「高速に取得する v2」ですが、以前書いた記事

【AWS Athena】クエリ実行結果のデータを高速にPandas.DataFrameとして取得する

の続編的な形になるため、そのように書いています。
Python3上でSQLを書いてデータを取得するときは、pyathenaよりawswranglerのほうが圧倒的に早いよ ということを書きたいというのが趣旨です。

環境・使用ライブラリ

2種類あります
それぞれ箇条書きのリンク先は実際に計測したcolaboratoryとなっています

colaboratory (Python 3.7.12)

結果

500万行10列のデータを50.8秒(ctas_approach=True)で展開することができました
ctas_approach=Falseの場合でも1分26秒でした

pyathenaライブラリを使用した場合、24分38秒もかかってしまいました

データ取得方法

環境・使用ライブラリにも実際のcolaboratoryリンクを貼っていますが、awswranglerでのデータ取得方法をこちらにも記載します
boto3.SessionにAWSの秘密鍵やリージョン情報を記載して、awswranglerを動かします

python
import awswrangler as wr
import boto3
import pandas as pd

# boto3.Sessionへ秘密鍵とリージョンを記載する
session = boto3.Session(
    aws_access_key_id=access,
    aws_secret_access_key=secret,
    region_name = 'ap-northeast-1'
)

# データを取得する(ctas_approach = True)
df = wr.athena.read_sql_query("SELECT * FROM big_parquet_data", database="main_data", boto3_session=session)

# データを取得する(ctas_approach = False)
df = wr.athena.read_sql_query("SELECT * FROM big_parquet_data", database="main_data", boto3_session=session, ctas_approach=False)

# データを取得する s3出力先やワークグループがある場合
df = wr.athena.read_sql_query(
    "SELECT * FROM big_parquet_data", database="main_data",
     boto3_session=session, workgroup='workgroup', s3_output='s3://*******'
)

read_sql_queryのその他引数についてはこちらに記載されています
https://aws-data-wrangler.readthedocs.io/en/stable/stubs/awswrangler.athena.read_sql_query.html

ctas_approachについて

Trueにすると、s3からparquetとして読み込むため大規模なデータのダウンロードスピードが速くなります。
ただし、AWS Glueでテーブルの作成/削除権限が別途必要です。その分料金も別で掛かります。

Falseにすると、単一のcsvから読み込むためTrueの時よりは大規模なデータのダウンロードスピードが遅くなります。(それでも速い)
AWS Glueの権限は必要ありません。

Windows環境での文字化け対処

文字エンコードの関係で、ctas_approach=Falseの状態でcsvを読み込むと、文字化けしたり

 'cp932' codec can't decode byte 0x86 in position 29: illegal multibyte sequence

等と、エラーが出ることがあります。

pyathenaと違い、データを取得する際にpandasを使用しないので、エンコード方法を指定することができません。
そこで、実行前に以下のコードを実行すると、WindowsがデフォルトでUTF-8エンコードとなり、文字化けやエラーを回避することができます。

文字化け直しコード
import os
if os.name == 'nt':
    import _locale
    _locale._getdefaultlocale_backup = _locale._getdefaultlocale
    _locale._getdefaultlocale = (lambda *args: (_locale._getdefaultlocale_backup()[0], 'UTF-8'))

対処例

日本語の入ったデータを作って、比較してみます

sql
CREATE TABLE main_data.name_list AS
SELECT * FROM (
    VALUES
        (1, '田中'),
        (2, '佐藤'),
        (3, '大森')
) AS t (id, name)
対処前
display(wr.athena.read_sql_query("SELECT * FROM name_list", database="main_data", boto3_session=session, ctas_approach=False))
id name
0 1 逕ー荳ュ
1 2 菴占陸
2 3 螟ァ譽ョ
対処後
import os
if os.name == 'nt':
    import _locale
    _locale._getdefaultlocale_backup = _locale._getdefaultlocale
    _locale._getdefaultlocale = (lambda *args: (_locale._getdefaultlocale_backup()[0], 'UTF-8'))

display(wr.athena.read_sql_query("SELECT * FROM name_list", database="main_data", boto3_session=session, ctas_approach=False))
id name
0 1 田中
1 2 佐藤
2 3 大森

文字化けを解消することができました!

最後に

大規模データのダウンロードもこれで快適です!
更に改善点などあれば教えていただけると助かりますm(__)m

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?