Selectorsで特定のモデルをdbt runの対象外にしてみた

オプションを指定せずにdbt runしたときに特定のモデルだけ除外できないか試してみました

はじめに

データアナリティクス事業本部のおざわです。

オプションを指定せずにdbt runを実行すると、プロジェクト内の有効なモデルがマテリアライズ(実体化)されます。なにも指定せずにdbt runした場合に、特定のモデルを除外できないか試してみたところ、Selectorsを使えば目的の動作ができましたので共有したいと思います。

今回使ったdbtのバージョンです。

❯ dbt --version
Core:
  - installed: 1.7.7
  - latest:    1.7.7 - Up to date!

Plugins:
  - redshift:  1.7.3 - Up to date!

Selectorsとは

今回使うSelectorsは、一言でいうとリソースの選択方法に名前を付けておく機能です。

使い方としては、selectors.ymlにリソースの選択方法を定義しておきます。あとはコマンドを実行する時に--selectorフラグにselector名を渡すだけです。

今回やってみたようにdefault: trueにすることで、なにもオプションを指定せずにdbt rundbt testを実行したときに処理する対象のリソースを変更できます。

プロジェクト構成

参考まで、プロジェクト構成になります。Selectorsはプロジェクト直下のselectors.ymlに定義します。 今回、除外対象としたモデルはexclude_me_modelです。モデルの中身はとくに重要ではないので割愛します。

my_project  
├── ...
├── models  
│ ├── marts  
│ │ ├── customers.sql  
│ │ ├── exclude_me_model.sql  
│ │ └── schema.yml  
│ ├── staging  
│ │ ├── staging.yml 
│ │ ├── stg_customers.sql  
│ │ └── stg_orders.sql  
│ └── source.yml  
├── dbt_project.yml
├── selectors.yml  
└── tests  
└── ...

設定なしでdbt runとdbt test

selectors.ymlにはなにも書いていない状態でdbt runしてみると、全てのモデルが実行されています。

07:13:04  Running with dbt=1.7.7
07:13:04  Registered adapter: redshift=1.7.3
07:13:04  Found 1 seed, 4 models, 3 tests, 3 sources, 0 exposures, 0 metrics, 455 macros, 0 groups, 0 semantic models
07:13:04  
07:13:05  Concurrency: 1 threads (target='dev')
07:13:05  
07:13:05  1 of 4 START sql view model public.stg_customers ............................... [RUN]
07:13:07  1 of 4 OK created sql view model public.stg_customers .......................... [SUCCESS in 1.97s]
07:13:07  2 of 4 START sql view model public.stg_orders .................................. [RUN]
07:13:09  2 of 4 OK created sql view model public.stg_orders ............................. [SUCCESS in 1.71s]
07:13:09  3 of 4 START sql view model public.exclude_me_model ............................ [RUN]
07:13:10  3 of 4 OK created sql view model public.exclude_me_model ....................... [SUCCESS in 0.83s]
07:13:10  4 of 4 START sql view model public.customers ................................... [RUN]
07:13:11  4 of 4 OK created sql view model public.customers .............................. [SUCCESS in 1.14s]
07:13:11  
07:13:11  Finished running 4 view models in 0 hours 0 minutes and 6.95 seconds (6.95s).
07:13:11  
07:13:11  Completed successfully
07:13:11  
07:13:11  Done. PASS=4 WARN=0 ERROR=0 SKIP=0 TOTAL=4

dbt testも実行してみます。除外対象のモデルを含めて3つのテストを入れています。

❯ dbt test
07:13:38  Running with dbt=1.7.7
07:13:39  Registered adapter: redshift=1.7.3
07:13:39  Found 1 seed, 4 models, 3 tests, 3 sources, 0 exposures, 0 metrics, 455 macros, 0 groups, 0 semantic models
07:13:39  
07:13:40  Concurrency: 1 threads (target='dev')
07:13:40  
07:13:40  1 of 3 START test not_null_customers_customer_id ............................... [RUN]
07:13:40  1 of 3 PASS not_null_customers_customer_id ..................................... [PASS in 0.40s]
07:13:40  2 of 3 START test not_null_exclude_me_model_customer_id ........................ [RUN]
07:13:41  2 of 3 PASS not_null_exclude_me_model_customer_id .............................. [PASS in 0.46s]
07:13:41  3 of 3 START test unique_customers_customer_id ................................. [RUN]
07:13:41  3 of 3 PASS unique_customers_customer_id ....................................... [PASS in 0.32s]
07:13:41  
07:13:41  Finished running 3 tests in 0 hours 0 minutes and 2.63 seconds (2.63s).
07:13:41  
07:13:41  Completed successfully
07:13:41  
07:13:41  Done. PASS=3 WARN=0 ERROR=0 SKIP=0 TOTAL=3

Selectorsで特定のモデルを除外してみる

今回はモデルにタグを設定して、そのタグが設定されたモデルを除外します。 タグについてはこちらのブログで紹介されていますのでご参照ください。

selectors.ymlでは以下のように設定しました。 unionで2つの条件を組み合わせています。fqnにワイルドカードを指定して全てのモデルを対象にし、excludeを使ってexclude_meでタグ付けされたモデルを除外しています。

defaultは基本的に1つのselectorでtrueにできますが、環境に応じて切り替える方法もドキュメントで紹介されています。

selectors.yml

selectors:
  - name: my_default_selector
    description: exclude tagged models by default
    default: true
    definition:
      union:
        - method: fqn
          value: "*"
        - exclude:
          - method: tag
            value: "exclude_me"

モデルには以下のようにexclude_meタグを付けています。

schema.yml

version: 2

models:
  - name: exclude_me_model
    config:
      tags: "exclude_me"
    description: My lovely model
    columns:
      - name: customer_id
        tests:
          - not_null

dbt run と dbt testを実行

以上、設定してからdbt runしてみます。 Using default selector my_default_selectorと出力され、除外対象のモデルは実行されません。

❯ dbt run
07:58:26  Running with dbt=1.7.7
07:58:26  Registered adapter: redshift=1.7.3
07:58:26  Found 1 seed, 4 models, 3 tests, 3 sources, 0 exposures, 0 metrics, 455 macros, 0 groups, 0 semantic models
07:58:26  Using default selector my_default_selector
07:58:26  
07:58:27  Concurrency: 1 threads (target='dev')
07:58:27  
07:58:27  1 of 3 START sql view model public.stg_customers ............................... [RUN]
07:58:29  1 of 3 OK created sql view model public.stg_customers .......................... [SUCCESS in 1.93s]
07:58:29  2 of 3 START sql view model public.stg_orders .................................. [RUN]
07:58:31  2 of 3 OK created sql view model public.stg_orders ............................. [SUCCESS in 2.07s]
07:58:31  3 of 3 START sql view model public.customers ................................... [RUN]
07:58:32  3 of 3 OK created sql view model public.customers .............................. [SUCCESS in 1.18s]
07:58:33  
07:58:33  Finished running 3 view models in 0 hours 0 minutes and 6.62 seconds (6.62s).
07:58:33  
07:58:33  Completed successfully
07:58:33  
07:58:33  Done. PASS=3 WARN=0 ERROR=0 SKIP=0 TOTAL=3

dbt testもやってみます。こちらもUsing default selector my_default_selectorと出力され、除外対象のモデルではテストが実行されませんでした。

❯ dbt test
08:00:33  Running with dbt=1.7.7
08:00:33  Registered adapter: redshift=1.7.3
08:00:33  Found 1 seed, 4 models, 3 tests, 3 sources, 0 exposures, 0 metrics, 455 macros, 0 groups, 0 semantic models
08:00:33  Using default selector my_default_selector
08:00:33  
08:00:34  Concurrency: 1 threads (target='dev')
08:00:34  
08:00:34  1 of 2 START test not_null_customers_customer_id ............................... [RUN]
08:00:34  1 of 2 PASS not_null_customers_customer_id ..................................... [PASS in 0.33s]
08:00:34  2 of 2 START test unique_customers_customer_id ................................. [RUN]
08:00:35  2 of 2 PASS unique_customers_customer_id ....................................... [PASS in 0.34s]
08:00:35  
08:00:35  Finished running 2 tests in 0 hours 0 minutes and 1.84 seconds (1.84s).
08:00:35  
08:00:35  Completed successfully
08:00:35  
08:00:35  Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2

おわりに

以上、Selectorsを使って特定のモデルを除外してみました。除外対象を含めたすべてのモデルを実行したい場合は、allのようなSelectorを作っておくのが良いと思います。

selectors.yml

selectors:
    # 省略
  - name: all
    description: all models
    definition:
      union:
        - method: fqn
          value: "*"

また、除外対象だけを実行したい場合は、普通に--selectでタグ指定すれば実行できます。

❯ dbt run --select "tag:exclude_me"
01:02:22  Running with dbt=1.7.7
01:02:22  Registered adapter: redshift=1.7.3
... 省略 ...
01:02:26  Finished running 1 view model in 0 hours 0 minutes and 3.58 seconds (3.58s).
01:02:26  
01:02:26  Completed successfully

参考リンク