BigQuery だけマテリアライズドビュー対応が Draft で止まっていることに気づいてしまいました in dbt-core v1.6.0

2023-08-04

はじめに

Data Platform チーム所属の dach です。

データ分析基盤を支える Data Stack の中の一つ、 ELT/ETL 処理における 「T (Transform)」の代表的なツール「dbt」は皆さんご存じのことかと思います。そんな dbt ですが、先日 2023-08-01 に dbt-core/v1.6.0 が Release されました。 v1.6.0 の更新では多数の新機能に加え、dbt-metrics が dbt-semantic-interfaces に変わるなど、大きな変更がありました。本記事では、v1.6.0 で追加された機能の一つである「materialized view サポート」について実際に試そうとしてだめだったお話をしようと思います。

※ 検証では下記を利用しています

  • version: dbt-core/v1.6.0
  • Adapter: BigQuery

materialized view とは?

以前の記事1で Materializations(マテリアライゼーション)とはなにか、そして v1.5 までは全部で 4 種類存在することを説明しました。v1.6.0 では「materialized view」が 5 つめとして追加されました2。 ご存知の方も多いと思いますが、まずは materialized view について改めてどのようなものかを整理したいと思います。 興味ない・既に知っているよ、という方は次の「どのように materialized view を構築するのか」から参照してください。

今回は、BigQuery の materialized view にフォーカスして説明するため、細かいポイントは異なるかもしれませんが、ご了承のほどよろしくお願いします。 以下に view と table と比較した materialized view のポイントを整理しました。

Materializations特徴メリットデメリット
viewSQL クエリによって定義されるため、実体は存在しない- 計算ロジックが参照できる
- ストレージコストがかからない
- 参照がある度クエリコストが発生するため、利用頻度が高い場合はコストがかさむ
- クエリ負荷が高いもの(データ量の多いテーブルへの処理や複雑な変換処理など)はレスポンスまでに時間がかかる
table物理テーブルとして実体を持つ- 特定時点のデータの状態を保持できる
- レスポンスが早い
- 複雑な変換がある場合、テーブルの再構築に時間がかかることがある
- 更新が必要な場合には手動で再実行する必要がある
materialized viewキャッシュに保存した SQL クエリの結果を返し、差分がある場合はベーステーブルから差分のみを読み取る- レスポンスが高速で、消費リソースも少ない
- ベーステーブルの更新に合わせて自動的に再計算されるため、メンテ不要
- 利用できるクエリが限定的である
- データ更新タイミングに対する考慮が必要
- どの DBMS でもサポートされているわけではない

基本的には materialized view を使っておけば良い!ということではなく、materialized view にも制限があるので、環境ごとにユースケースとマッチするかを見極める必要があります。

materialized view を構築しようとしてエラーで怒られた

dbt は先日 2023-08-01 に dbt-core/v1.6.0 を Release しました。 CHANGELOG を眺めると、新機能の一部になんと「Add support for materialized views (#6911)」との記載があるではありませんか!これはいいネタだと思った私は、早速ブログの準備をしつつ「構築してみてどうだったかの話」を書こうと動きました。どのように実行するべきか、どういうパラメータがあるのかをチェックするために公式ドキュメントをチェックします。 この時点で気づくべきだったのかもしれません。なんと、materialized view についての記載がまだないではありませんか。仕方なく、Issue の中身を見ながら進めることにしました。その時まだ、私は致命的なミスをしていたことに気づきませんでした。

まずは、手元の dbt を v1.6.0 に upgrade をして、サンプルモデルを準備します。 Issue を見ると、materialization の指定は materialized_view を使う様だったので、試しに設定して dbt run してみました。

[tool.poetry.dependencies]
python = "~3.11"
dbt-core = "1.6.0"
dbt-bigquery = "^1.6.0"
{{
    config(
        materialized='materialized_view'
    )
}}

with
_spine as (
    {{ dbt_utils.date_spine(
        datepart="month",
        start_date= "'2023-01-01'",
        end_date= "'2023-03-01'"
    )
    }}
),

_quarter_first as (
    select cast(date_month as date) as target_month
    from _spine
)

select * from _quarter_first

上記を実行したときの結果がこちらです。

06:32:32  Completed with 1 error and 0 warnings:
06:32:32
06:32:32  Compilation Error in model quarter_first (models/utilities/quarter_first.sql)
06:32:32    Materialized views have not been implemented for this adapter.
06:32:32
06:32:32    > in macro default__get_replace_materialized_view_as_sql (macros/materializations/models/materialized_view/replace_materialized_view.sql)
06:32:32    > called by macro get_replace_materialized_view_as_sql (macros/materializations/models/materialized_view/replace_materialized_view.sql)
06:32:32    > called by macro materialized_view_get_build_sql (macros/materializations/models/materialized_view/materialized_view.sql)
06:32:32    > called by macro materialization_materialized_view_default (macros/materializations/models/materialized_view/materialized_view.sql)
06:32:32    > called by model quarter_first (models/utilities/quarter_first.sql)

Materialized views have not been implemented for this adapter

「おや?Adapter が対応してないだって?そんな馬鹿な」
そんなことを呟きながら、Issue を良く確認してみると、BigQuery だけマテリアライズドビュー対応が Draft で止まっていることに気づいてしまいました。

image

そう、Issue はまだ Open だったのです!! ここで私は致命的なミスをしていたことに気づきました。 image2

当然、dbt-bigquery Issue 側の更新も、Issue が立った頃から特になく、Draft PR も 2023−05−31 以降、特に更新はありませんでした。 はじめにきちんと確認していれば、ぬか喜びをしないですんだ話だった、というわけです。

まとめ

本記事では、情報をきちんと確認することの大事さについて紹介しました。 他のサポートされている Adapter でも、コンテナイメージのパッケージがまだ公開されてないものもあるので、利用の際には注意が必要となります。

Data Platform チームでは、よりスピーディーにより高品質なデータを提供できるようにするメンバーを更に募集中です。興味を持って頂けた方は是非以下もご覧頂ければ幸いです

Footnotes

  1. dbt Materializations はレイヤーによって何を選ぶべきか決まっていることを知っているか

  2. BigQuery と Redshift と Postgres のみが対応されているようです(参照