Materialized View を go で作る

BigQuery に Materialized View がβリリースされました。

https://cloud.google.com/bigquery/docs/materialized-views-intro

go の Client Library で作成してみます。 https://godoc.org/cloud.google.com/go/bigquery

ctx := context.Background()

projectId, err := metadata.ProjectID()
if err != nil {
    log.Fatal(err)
}

sql := `
  SELECT
    timestamp,
    day, 
    AVG(weight_pounds) AS weight_pounds
  FROM
    hoge.natality
  GROUP BY
    timestamp, 
    day  
`

// 1時間
refreshInterval := time.Duration(3600000)*time.Millisecond

view := &bigquery.MaterializedViewDefinition {
    EnableRefresh: true, // 自動更新を有効
    LastRefreshTime: time.Now(), // 設定するとテーブル情報に含まれる
    Query: sql,
    RefreshInterval: refreshInterval,
}

// クラスターインデックス
cluster := &bigquery.Clustering{
    Fields: []string{"day"},
}

// パーティショニングテーブル
timePartitioning := &bigquery.TimePartitioning {
    Expiration: 0,
    Field: "timestamp",
}

metaData := &bigquery.TableMetadata{
    MaterializedView: view,
    ExpirationTime: time.Now().Add(24*time.Hour), // View の有効期限
    TimePartitioning: timePartitioning,
    Clustering: cluster,
}

client, err := bigquery.NewClient(ctx, projectId)
if err != nil {
    log.Fatal(err)
}

tableRef := client.Dataset(datasetId).Table("natality_02")
if err := tableRef.Create(ctx, metaData); err != nil {
    log.Fatal(err)
}


下記は色々触ってみた感想です。

Materialized View と Base Table に対して同様のクエリを実行して、レスポンス速度と消費スロット数を比較してみたところ、Base Table より Materialized View の方がレスポンス速度は約40%ほど速く、消費スロット数は約1/25でした。

Base Table が TimePartitioning されていた場合は上記の差分が無くなったので、
Base Table が TimePartitioning されていないケースで使うと効果的なのかなという印象です。

View に TimePartitioning と Clustering の設定は可能でした。 ただ、計測では TimePartitioning と Clustering を設定していない View と比較して、 レスポンス速度は下がり、消費スロット数は上がるという結果だったので、設定は不要かもしれません。

幅広く使えそうなイメージで調べてましたが、細かな挙動を確認していくと使い所に悩む機能だなと思いました。 どこかで使いたいっ!!