dbt Cloud を学んでみる - モデルの形式・依存関係を設定してみる

前回 [dbt Cloud のモデル作成が完了](https://qiita.com/ny94/items/dc500d013e2cb739a264) しました。

（だいぶ期間があいてしまいましたが。。）今回は引き続き、モデル設定について確認してみます。
モデルに関する設定の中でも特に大きな2つの要素が、 **①マテリアライゼーション** と **②依存関係** についてです。

# マテリアライゼーション
マテリアライゼーションは、ウェアハウス内に保存する際の形式（テーブルなのか、ビューなのか…等）の設定です。

↓　サンプルの【my_first_dbt_model】について見てみます。★の一文にて、マテリアライゼーション ＝ テーブル と設定されています。

```SQL:my_first_dbt_model.sql
{{ config(materialized='table') }}  -- ★

-- //途中省略

select *
from source_data
```

実際の「dbt run」実行結果を確認すると、確かにテーブルとして作成されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/0c84eaf5-6981-c9ea-a527-7b48db9eaa4b.png)

マテリアライゼーションはデフォルトではビューになります。
そのため、何も指定しなかった【customers】と【my_second_dbt_model】はビューで作成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/abfa6bbc-6abc-5fef-0416-a940120d539f.png)

なお、マテリアライゼーションとして選択できる形式は、テーブル、ビュー含めて4つあるそうで
* table：テーブル
* view：ビュー
* incremental：差分更新する形式（前回実行時からの登録、更新レコードをテーブルに反映するらしい）
* ephemeral：データベースに組み込まれない、共通テーブル式として使用する

とのこと。

## 設定方法
設定方法は2通りです。

1. dbt_project.yml で設定
1. 各モデル定義内のconfigブロック で設定　※サンプル【my_first_dbt_model】の方法

### 1. dbt_project.yml で設定
dbt_project.yml はプロジェクト全体の設定ファイルなので、複数のモデルをまとめて設定することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/00359023-e2e0-ebc7-3ebe-ee43bfd2d221.png)

```yaml:dbt_project.yml
name: 'jaffle_shop’

# //途中省略

models:
  jaffle_shop:
    +materialized: table
    example:
      materialized: view
```
↑　の記述で、

プロジェクト（jaffle_shop）配下のすべてのモデルに **マテリアライゼーション＝テーブル** を設定、
ただし、 example/ の配下については個別に **マテリアライゼーション＝ビュー** を設定している。

ということになります。

　↓　この設定で「dbt run」を実行すると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/63ca4c67-4dcd-9980-eb02-26f18fec24c2.png)
設定どおり、【customers】が今度はビューではなく、テーブルで作成されました。
【my_second_dbt_model】の方は、example/ 配下なのでビューのままです。

### 2. 各モデル定義内のconfigブロック で設定
個別のモデルに設定するのであれば、モデルファイル内にconfigブロックで記述することもできます。

```SQL:customers.sql
{{ config(materialized='view') }}  -- ★configブロックで記述

-- //省略

```

↑　の記述で、customersモデルを **マテリアライゼーション＝ビュー** を設定してみました。

このとき、customersモデルは dbt_project.yml で **マテリアライゼーション＝テーブル** に設定されていながら、
モデル定義内のconfigブロックでは**マテリアライゼーション＝ビュー** を設定されているということになります。

このように重複して設定がされている場合、実行結果はどうなるかというと・・


　↓　「dbt run」を実行・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/7c859eed-d347-d94c-badb-d838f9495bc0.png)

configブロックの設定が勝ち、ビューで作成されました。

:::note info
設定は、【モデル定義内のconfigブロック > dbt_project.yml】の順で優先されます。

まとめての指定よりも、**詳細な指定の方が優先**となるそう。

ymlファイル内複数定義した場合も細かい方が優先なので、【下位のディレクトリで指定した定義 > 上位ディレクトリで指定した定義】だそうです。
:::

# 依存関係
↓　サンプルの【my_second_dbt_model】は★のref関数にて、依存関係が設定されています。

```SQL:my_second_dbt_model.sql
select *
from {{ ref('my_first_dbt_model') }}  -- ★
where id = 1
```

この記述により、dbtは実行時にモデル間の依存関係を認識して、
【my_first_dbt_model】→【my_second_dbt_model】の順でビルドするという動きをしてくれます。

## 設定方法
```{{ ref('依存先モデル名') }}```をsqlのfrom部分に当てはめます。（テーブルやサブクエリと置き換えるだけなので、『設定』という感じはしませんね、、）

とりあえずやってみたいので、前回作成したcosutomersモデルのサブクエリを分離して、依存関係を設定してみました。

```SQL:cosutomers.sql
with customers as (
    select * from {{ ref('stg_customers') }}  -- ★依存関係１
),
orders as (
    select * from {{ ref('stg_orders') }}  -- ★依存関係２
),

-- //途中省略

select * from final
```

```SQL:stg_customers.sql
select
    id as customer_id,
    first_name,
    last_name
from raw_db.jaffle_shop.customers
```

```SQL:stg_orders.sql
select

-- //途中省略

from raw_db.jaffle_shop.orders
```

これで「dbt run」実行・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/58b5a785-2bf4-0627-ceeb-7b95704f42f6.png)
↓　の依存関係に従って、順序どおりビルドされたことが分かります
* 【stg_customers】&【stg_orders】 → 【customers】

依存関係を設定するメリットは、視覚的に認識しやすいリネージグラフをdbtが自動で作成してくれるというものもあります。
↓　はIDE画面の表示ですが、後で触れる自動作成のドキュメントにも、同様のリネージグラフを生成してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333083/2421563e-df0f-1beb-8b15-7853f45d8800.png)


---
マテリアライゼーションと依存関係の設定を試してみることができました。

他にもモデル（そのほかのdbtオブジェクトもそうですが）に付加できる設定には様々な種類のものがあります。
ひとまず設定方法のパターンや雰囲気はつかめたので、後は都度都度[公式リファレンス](https://docs.getdbt.com/reference/references-overview)を確認しながら使用してみようと思いました。

次回はテストとドキュメント化に挑戦してみたいと思います。