dbt build --emptyが_TABLE_SUFFIXや_PARTITIONTIMEが原因で実行できないときの対処法
dbt core 1.8から空のリソースを作成することができる --empty
フラグが追加されている。
このフラグを指定すると、裏側では limit 0
という条件が追加され、出力が空になるのはもちろん、スキャン量がゼロになる。
この機能は色々なところで使い道があり、
- クエリは書けたので、まずはSELECT文に不備がないか簡単に確認したいとき
- dbt-osmosisでyamlを書きたいので、空テーブルで良いので作成しておきたいとき
などが思いつく。特に最近はUSDが高く、スキャン量が大きいクエリをdebug目的で連発するのは気が引けるため、こういったコスト削減に繋がる機能は地味に有難い。
ただ、この機能を使うときに注意が必要なのが、_TABLE_SUFFIX
や_PARTITIONTIME
などの疑似列を参照しているクエリの場合だ。
例えば以下のようなモデルがあったとする。
SELECT
*
FROM
{{ source("ga4", "events_*") }}
WHERE
_TABLE_SUFFIX BETWEEN FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9") -3 )
AND FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9"))
このモデルに対して、dbt build --emptyを実行すると、以下のようなエラーになる。
Unrecognized name: _TABLE_SUFFIX at [6:3]
compileされたクエリを見てみると、以下のようになっている。
SELECT
*
FROM
(select * from `bigquery-public-data`.`ga4_obfuscated_sample_ecommerce`.`events_*` where false limit 0)
WHERE
_TABLE_SUFFIX BETWEEN FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9") -3 )
AND FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9"))
挙動としては、 --empty
フラグを付けると、sourceやrefで参照しているデータソースがlimit 0
をつけたサブクエリとしてラップされるのだが、
サブクエリの select *
が実行されたタイミングで疑似列は保持されなくなるため、そのあとのクエリで _TABLE_SUFFIX
参照することができなくなりエラーになっている。
この挙動については、1.8リリース直後に早速報告されているが、実際のところ、この挙動はバグではないので回避策を考える必要がある。
比較的シンプルな対応方法として以下のissue内でも言及されているのが、jinja内で使用できる flags
というcliでの指定有無を判別する変数を使う方法だ。
dbt-coreのコードを見ないと細かいことは分からないが、判別結果としてTrue/Falseが格納されており、is_incremental
と同じような使い方ができることが分かる。
スキャン量ゼロであれば、 _TABLE_SUFFIX
でのフィルターも不要になるので、あとはこの変数を使って、--empty
フラグが指定された場合は_TABLE_SUFFIX
を参照しないようにすれば良い。
SELECT
*
FROM
{{ source("ga4", "events_*") }}
{% if not flags.EMPTY %}
WHERE
_TABLE_SUFFIX BETWEEN FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9") -3 )
AND FORMAT_DATE("%Y%m%d", CURRENT_DATE("+9"))
{% endif %}
とはいえ、この方法にも若干問題があり、require_partition_filter = true
が設定されており、パーティション列として_PARTITIONTIME
などを使用しているテーブルではクエリが実行できない。
その場合は
- require_partition_filterを外す
- 疑似列パーティションを使わずに、実データをパーティション列に指定する
-
issue内のコメントにあるように、他のjinja関数と組み合わせて
--empty
の挙動を書き換える
くらいしかない。ただ、dbtはアップデートも早いので、1.9が出る頃にはもっと良い方法が用意されているかもしれない。
また、こうしたdbt固有の変数や関数は便利な反面、新規メンバーの学習コストが跳ね上がるため、過度な使用は控えた方が良いだろう(使いこなせることに憧れは感じつつも)。
Discussion