この記事はGo3 Advent Calendar 2020の22日目です。
こんにちは、Speeeでサーバーサイドエンジニアをしている@muroon01です。SpeeeではUZOUという広告配信プラットフォームの開発をしています。 今回はGoでAthenaにアクセスするOSSを開発しましたのでそちらの話をさせていただきます。
こちらは元々別の方々が作成されたものですが、 2年近くメンテナンスされてないようなので改修することにいたしました。
go-athena
go-athenaはdatabase/sqlパッケージのAthenaのdriverです。下記のように(初期化)importをして使用します。
import ( "database/sql" _ "github.com/speee/go-athena" ) func main() { db, _ := sql.Open("athena", "db=default&output_location=s3://results") rows, _ := db.Query("SELECT url, code from cloudfront") for rows.Next() { var url string var code int rows.Scan(&url, &code) } }
追加機能
もともと上がっていたIssueのいくつかを取り込むことなどを含め下記の機能を追加しました。
- Docker環境追加
- reviewdog
- DDL実行時のResultHeaderの削除
- workgroupの使用
- testの修正(各packageを最新にあわせる)
- クエリのResult取得モードを新たに設ける
クエリのResultモードを設ける
アプリケーションからAthenaにクエリを投げてクエリの結果を取得するのに大きく2種類のAPIコールが必要です。
- クエリの実行
- クエリの実行した結果(SELECT文のRows)を取得
元々go-athenaはGetQueryResults APIアクセスによりクエリ結果を取得してました。 GetQueryResult APIアクセスはクエリ結果を全件取得するためには取得レコード件数によっては複数回アクセスする場合もありました。 Athenaにはクエリ結果をファイルダウンロードする機能やCTASテーブルを作成・閲覧する機能があるのでそれらを使用してクエリの実行結果を取得するためにResultモードを設けました。
- APIモード(default)
- DLモード
- GZIP DLモード
ただし、DLモード、GZIP DLモードはSelect文でのみ使用可能です
APIモード
結果取得にGetQueryResults APIにアクセスして結果を取得します。 このAPIアクセスはクエリ結果をAPIで返す場合はレスポンスで返せる件数に制限があります。クエリ結果が一定の件数(手動指定の場合は最大1000件)を超える場合は複数回のAPIアクセスにて全クエリ結果を取得します。
DLモード
Athenaはクエリ結果の全件をcsvファイル保存しています。それをダウンロード取得することによりクエリ結果の件数に関係なく1APIアクセスで取得が可能です。ただしcsvファイルは無圧縮です。この方法はPyAthenaでも使用されています。
GZIP DLモード
DLモードのcsvファイルは無圧縮のファイルダウンロードでした。 CTASテーブルを使用することによりダウンロードファイルをgzipに圧縮することが可能です。
- クエリによるCTASテーブル作成(gzip指定)
- CTASテーブルデータのダウンロード・解凍
- CTASテーブルを削除
各モードのレスポンス時間
クエリ実行から結果全件取得までかかった時間の比較です。
下記の傾向が言えるかと思います。
- 少量の件数ではDLモード、APIモードが有効
- 大量の件数ではGZIP DLモードが非常に有効
最後に
もしfork元のRopositoryのメンテナンスが復活したら
管理者の方が望まれるようであれば、Speee版を取り込んでもらえたらと考えております。
go-athnaパッケージはdatabase/sqlパッケージにてAthenaを使用できる点がGoの開発者にとってとてもなじみやすいのでいいパッケージだと思います。
Speee版は溜まっていたIssueの解決だけでなく新規の機能もございますので、オリジナルを作られた方々にも是非気に入っていただければ思っております。