GMOアドマーケティングに中途入社してまもないy.yです。
11/5(日)のGo Conferenceの内容についてまとめようと思っていたのですが
補欠からくり上がれなかったので今回はGo言語を使って
Google Cloud Storageへのアップロードをし、BigQueryでの集計手順について記載します。
本題に入る前にGo言語を選んだ理由
マスコットキャラクターのGopherくんが可愛かった 😀
Gopherくんはホリネズミという動物がモチーフらしいです。
どうでしょう?世界のミッキー○ウス並みにGopherくん可愛くないですか??
@tentenのGopher by CC BY 3.0
公式のGopherくんはきも可愛いですね 😀
The Go Blog by CC BY 3.0
Gopherくんについて詳しく知りたい方は Gopherくん入門 へ!
Gopherくんが可愛いから選んだというのは冗談で
実際は下記の2点でGo言語を選択しました。
- いくつかの言語でパフォーマンスを計測した結果、Go言語のパフォーマンスが一番良かった。
- 並列処理でログをparseするのにGo言語が簡単だった。
ここから本題の手順を記載いたします。
- Google Cloud Storageへのアップロード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
func GcsPut(bktName string, objName string, path string) error { ctx := context.Background() // Creates a client. client, err := storage.NewClient(ctx) if err != nil { return err } defer client.Close() w := client.Bucket(bktName).Object(objName).NewWriter(ctx) // option w.ObjectAttrs.ContentType = "application/octet-stream" w.ChunkSize = 1024 defer w.Close() f, err := os.Open(path) if err != nil { return err } defer f.Close() if _, err = io.Copy(w, f); err != nil { log.Fatal(err) } return nil } |
ContentType | 型:String
ContentTypeを指定します。 |
ChunkSize | 型:Int
指定したサイズを上限にオブジェクトを分割してアップロードする指定。 1回のリクエストでアップしたい場合はCunkSizeを指定。 上限を指定しない場合は0または無指定。 |
容量の大きいObjectをUploadする際はネットワークに影響しないように制限した方がいいかもしれないですね。
- BigQueryへLoad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
func BigQueryLoad(config Config, gcspath string, tableid string) error { projectid := config.BigQuery.Projectid gcsuri := config.BigQuery.Gcsuri + gcspath datasetid := config.BigQuery.Datasetid ctx := context.Background() // Creates a client. client, err := bigquery.NewClient(ctx, projectid) if err != nil { return err } gcsRef := bigquery.NewGCSReference(gcsuri) // option gcsRef.AllowJaggedRows = true gcsRef.Compression = bigquery.Gzip gcsRef.MaxBadRecords = 1000 gcsRef.FieldDelimiter = "n" schema := bigquery.Schema{ &bigquery.FieldSchema{Name: "id", Required: true, Type: bigquery.IntegerFieldType}, &bigquery.FieldSchema{Name: "host", Required: false, Type: bigquery.StringFieldType}, &bigquery.FieldSchema{Name: "created_at", Required: true, Type: bigquery.StringFieldType}, } dataset := client.Dataset(datasetid) err = dataset.Table(tableid).Create(ctx, &bigquery.TableMetadata{ Schema: schema, }) if err != nil { return err } loader := dataset.Table(tableid).LoaderFrom(gcsRef) loader.CreateDisposition = bigquery.CreateNever job, err := loader.Run(ctx) if err != nil { return err } status, err := job.Wait(ctx) if err != nil { return err } if err := status.Err(); err != nil { return err } return nil } |
AllowJaggedRows | 型:bool
不正なレコードがあった場合、NULLとして扱うかエラーとして扱うかを選択します。 |
MaxBadRecords | 型:Int
不正なレコード数を許容するレコード数を指定します。 |
Compression | 型:String
Google Cloud StorageにuploadされたLoadするObjectの圧縮タイプを指定します。 |
FileDelimiter | 型:String
Loadされるファイルのdelimiterを指定します。 |
圧縮されたファイルをLoadをする場合はCompression、CSV形式ではないファイルをLoadする場合はFileDelimiterを指定しましょう。
- BigQueryで集計
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
func BigQueryFetch(config Config, query string, tableid string) error { projectid := config.BigQuery.Projectid datasetid := config.BigQuery.Datasetid ctx := context.Background() // Creates a client. client, err := bigquery.NewClient(ctx, projectid) if err != nil { return err } q := client.Query(query) q.UseLegacySQL = true q.Dst = &bigquery.Table{ ProjectID: projectid, DatasetID: datasetid, TableID: tableid, } q.AllowLargeResults = true log.Println("実行クエリ>>> " + query) it, err := q.Read(ctx) if err != nil { return err } for { var values []bigquery.Value err := it.Next(&values) if err == iterator.Done { break } if err != nil { return err } // ↓Todo 集計結果をDBに入れたり ... } dataset := client.Dataset(datasetid) // tableの保持期間の設定↓の場合は1時間経過したらtableが消えます。 _, err = dataset.Table(tableid).Update(ctx, bigquery.TableMetadataToUpdate{ ExpirationTime: time.Now().Add(1 * time.Hour)}, "") if err != nil { return err } return nil } |
UseLegacySQL | 型:bool |
LegacySQLを使用する場合はUseLegacySQLをtrueにしましょう。
ここまででGoogle Cloud Storageへのアップロード、BigQueryでの集計手順は終わりです。
どういったオプションがあるのか確認するのに時間が多少かかりましたが
アップロード、集計までの処理はサクッと簡単に書くことができました。
Go言語に関してまだまだ初心者なのでまずは中級者を目指したいと思います。
以上、Google Cloud Storageのアップロードから BigQueryでの集計の手順でした。
エンジニア採用
弊社は、広告をより便利な物にしていく事を一緒に目指してくれるエンジニアを募集しています。