Snowflake×dbtを試してみた~Part5:テスト&Doc&デプロイ編~ #SnowflakeDB #dbt

2021.12.23

※本エントリは、Snowflakeをより使いこなそう! Advent Calendar 2021の23日目の記事となります。

さがらです。

Snowflake公式のdbtと連携した時の機能を一通り試すことが出来るQUICKSTARTSに関して試してみた内容をまとめていきます。※この記事は「Part5:テスト&Doc&デプロイ編」となります。

この記事の内容について

Snowflake公式のQUICKSTARTSに、Accelerating Data Teams with dbt & SnowflakeというSnowflakeとdbtを組み合わせたときの利点を一通り試すことが出来るクイックスタートがあります。

こちらの内容について、以下の合計5本の構成で試してみた内容を書いていきます。

この記事では、「テスト&Doc&デプロイ編」ということで「13. dbt pipelines - Tests & Docs」から「16. Appendix」の内容についてまとめていきます。

13. dbt pipelines - Tests & Docs

ここでは、dbtを用いたテストとドキュメントについて見ていきます。

組織でデータ活用をするにあたり、データに対する信頼を築くには、テストとドキュメンテーションを整備しておくことはやはり重要です。テストの自動化とドキュメンテーションに関する方法は数多くありますが、dbtには標準機能として、データテストとドキュメンテーションの機能が備わっております。

dbtを用いたテストの定義・実行

dbtにおけるテストは、以下の4つに関するテストを提供しています。

  • uniqueness(値の一意であること)
  • not_null(値がNULLでないこと)
  • check constraints(値が条件を満たしていること)
  • relationship integrity(リレーションを作成した2つのテーブル間で、整合性があること ※参照整合性のこと)

早速、テストに関する定義をしていきましょう。

New Fileから、名前をmodels/marts/core/intermediate/intermediate.ymlに書き換えて、新しくファイルを作成します。

intermediate.ymlファイルが出来たら、以下の内容をコピーして貼り付けて、右上のsaveを押します。

version: 2
 
models:
  - name: int_fx_rates
    description: "An intermediate model that filters stg_knoema_fx_rates"
    columns:
      - name: currency||exchange_date
        tests:
          - unique
          - not_null
 
  - name: int_unioned_book
    description: "An intermediate model unions the manual_book csvs"
    columns:
      - name: instrument
        tests:
          - not_null
          - relationships:
              to: ref('int_knoema_stock_history')
              field: company_symbol
 
  - name: int_knoema_stock_history
    description: "An intermediate model that pivots the stg_knoema_stock_history model by indicator"
    columns:
      - name: company_symbol||stock_date
        tests:
          - not_null
          - unique

早速テストをしてみます!コマンドラインでdbt testと入力し、実行してください。

そしてログを見ると、not_null_my_first_dbt_model_idunique_int_knoema_stock_history_company_symbol_stock_dateにおいてテストが失敗していることがわかるはずです。

この内、unique_int_knoema_stock_history_company_symbol_stock_dateについて詳しく見ていきます。

対象項目のDetailsを押すと、テストとして失敗したクエリが表示されます。

ここで、以下のクエリを貼り付けて、スキーマ名を自身のものに変更した上でPreviewを押してください。※スキーマ名を変更する箇所が2つあるので注意してください。

with cst as
(
    select
        company_symbol||stock_date as conctat
    from <dev_schema>_marts.int_knoema_stock_history
    where company_symbol||stock_date is not null
    group by company_symbol||stock_date
    having count(*) > 1 
    limit 1
)
 
select * from <dev_schema>_marts.int_knoema_stock_history
where company_symbol||stock_date IN (SELECT conctat FROM cst)

このクエリは、テストに指定したキーがユニークであるかどうかを確かめるために実行したのですが、下図の結果の通り、テストに指定したユニークキーで2レコード以上存在するレコードがあったようです。この確認により、stock_exchange_nameもユニークキーとして指定しなければいけないことがわかりました。

intermediate.ymlファイルを開いて、内容を下記に書き換えてください。変更点としては、int_knoema_stock_historymodelのところで、|| stock_exchange_nameと追加しています。

version: 2

models:
  - name: int_fx_rates
    description: "An intermediate model that filters stg_knoema_fx_rates"
    columns:
      - name: currency||exchange_date
        tests:
          - unique
          - not_null

  - name: int_unioned_book
    description: "An intermediate model unions the manual_book csvs"
    columns:
      - name: instrument
        tests:
          - not_null
          - relationships:
              to: ref('int_stock_history')
              field: company_symbol

  - name: int_knoema_stock_history
    description: "An intermediate model that pivots the stg_knoema_stock_history model by indicator"
    columns:
      - name: company_symbol||stock_date||stock_exchange_name
        tests:
          - not_null
          - unique

ここで、1つ私の考えを記しておきます…

今回はクイックスタートに沿って実施しているだけですが、「データに合わせてテストの内容を変更する」というのは基本NGだと私は考えています。「テストが上手く通らないなら、テストの条件を変えてしまえ!」と言っているようなものですからね…。

今回の例でいうと、ユニークキーのテストケースを書き換える理想形としては、以下の流れが良いと考えています。

  1. 事前の処理設計でユニークキーを明確にしておく
  2. そのユニークキーをテストとして実装
  3. その後テストでエラーが発生したら、データ自体に異常がないかを疑い、調査をする(原因の例:DWHへの重複ロード、など)
  4. データ自体に異常がないことを確認した上で、事前のユニークキー処理設計が間違えていたことを認識し、テストの内容を書き換える

余談でしたが、テストは厳密に行わないと意味がないため、補足させて頂きました。

では改めて、テストを実行してみましょう!

コマンドラインにdbt test -m int_knoema_stock_historyと入力し、実行してください。

下図の通り、先程エラーになったunique_int_knoema_stock_history_company_symbol_stock_date_stock_exchange_nameがpassしていればOKのです!

dbtを用いたドキュメント生成

以前の章でも一度ドキュメントは生成していましたが、一通りmodelの定義を終えた現段階で改めてmodelを作成してみます。

コマンドラインで、dbt docs generateを実行して、生成されてドキュメントをview docsから開いてみてください。

ここで、これまでに生成したmodelについてのドキュメントを少し見てみます。

以下は先程テストでも確認したint_knoema_stock_historyについてのドキュメントですが、DescriptionAn intermediate model that pivots the stg_knoema_stock_history model by indicatorと記されているのがわかります。

実は先程作成したテストの中にdescriptionというパラメータがあり、この内容がドキュメントに適用されているのです。

dbtのドキュメントは、別のMarkdownファイルも参照させることで各カラムの定義を表に起こすことも可能です。ドキュメントについてより詳しく知りたい場合はこちらの記事も併せてご覧ください。

不要なデフォルトモデルの削除

先程のテスト結果でお気づきの方もいるかもしれませんが、exampleフォルダの中にあるmodelがあると、テストはエラーを出してしまいます。

そのため、exampleフォルダを削除しておきましょう。

exampleフォルダの横の「・・・」を押して、Deleteを押し、確認画面ではConfirmを押しましょう。

開発内容のCommit

ここまで完了したら、一通りの開発作業は終わりのため、内容をCommitしておきましょう。Commit Messageはset up test for intermediate modelsのような文言を入れておきましょう。

14. dbt pipelines - Deployment

これまでの工程で、パイプラインの開発、テスト、文書化など、一通り開発を行ってきました。

…が、これは別途切ったブランチ上での作業のため、まだ本番環境には何も影響を与えていません。 そこで、GitリポジトリのMasterブランチにマージして本番環境での実行設定を行う、デプロイ作業を行います。

Masterブランチへのマージ

13章の最後でCommitしていれば、左上には下図のようにmerge to masterと表示されているはずです。

一定時間後、下図のように、`branch: master(read-only)と表示されるはずです。これで、Masterブランチへこれまで開発した内容の適用(マージ)が完了しました!

本番環境へ適用させるための設定変更

続いて、本番環境へ適用させるための各種設定を行っていきます。(今回のクイックスタートではSnowflakeのPartner Connectを用いているので、少し設定を変更するだけで充分です。)

左上のメニューバーからEnvironmentsをクリックします。

続いて、Deplpyment➟右上のSettingsと続けてクリックします。

ここでは、Deploy時に適用されるスキーマ名を変更していきます。(デフォルトだとdbt_の形だと思います。)この場では本番環境のスキーマをproductionとし、変更していきます。本番環境のスキーマを明確に分けて置くことで、開発環境と混同せずに済みます。

右上のEditを押してください。

Deployment CredentialsSCHEMAを、productionに変更した上で、Saveを押してください。

ジョブの設定

最後に、ジョブの設定をしていきます。

左上のメニューバーから、Jobsをクリックします。

続いて、Partner Connectにより自動で作られたジョブPartner Connect Trial Jobをクリックし、右上のSettingsを押します。

ジョブの設定値が表示されますので、編集するために右上のEditを押します。

まず、ジョブのNAMEProduction Jobに変更します。これが本番稼動のジョブであることを名前から明示的にしておきます。

続いて、THREADSの値を8に変更します。この変更により、dbtはDAG内の8つのdbtモデルを依存関係なしに同時に実行することができるようになります。8は、Snowflakeで推奨されるデフォルトです。(クイックスタートの記載をそのまま引用しています。)

他の設定は変更しませんが、どんな設定ができるかを少し見ておきたいと思います。

まず、Commandsではこのジョブによりどのコマンドが実行されるかを順番付きで指定可能です。dbt seedによりcsvからデータをロードし、dbt runでmodelを一通り実行、dbt testでテストを実行する、という一連の流れが設定されています。

続いて、Triggersではこのジョブを何をトリガーにして実行するかを設定できます。自動実行させたい場合には必須のオプションですね。この場では手動でジョブを実行するためどのオプションも有効にしません。

ここまで、設定が終わったら右上のSaveを押してください。

続いて、Settingsよりひとつ上の階層に戻り、Run nowを押してこのジョブを実行します。

少し時間がかかると思います。終了後、実行したジョブを一覧から選択すると、どのような処理が行われたかを詳細に確認可能となっています。

15. Conclusion & Next Steps

dbtとSnowflakeを使用して、分析のためのデータ変換パイプラインを構築する方法を学びました。

  • dbtとSnowflakeのセットアップ方法
  • Snowflakeのデータマーケットプレイスでデータを活用する方法
  • dbtプロジェクトの実行とパイプラインの開発方法
  • データテストとドキュメントの作成方法

引き続き無料トライアルを続けて、ご自身のサンプルデータや本番データをロードし、dbt CloudとSnowflakeのより高度な機能にトライしていきましょう!

更にdbtを知るためには、以下のコンテンツがオススメです。

  • Slackのdbt communityこの記事でも紹介したとおり、全世界2万人を超えるユーザーが在籍しているコミュニティです。
  • 公式のトレーニング:英語にはなりますが、無料の学習コンテンツがありますのでそれを用いて学習することも可能です。
  • DevelopersIOのdbt記事:(これは公式には載っていないですが…笑)このDevelopersIOにおいても、多くのdbtの記事を執筆しておりますのでぜひご覧ください!

16. Appendix

ここでは、dbtで構築したデータの活用ということで、Snowflakeの可視化機能「Snowsight」を用いた可視化について少しだけ触れています。

Snowsightの画面から以下のクエリを実施すると、dbtで加工したデータを元に可視化することが出来ます。

select * 
from pc_dbt_db.<dev_schema>_marts.int_daily_position_with_trades
where trader = 'Tina M.'
order by  book_date

これはほんの一例ですが、dbtを用いてBIツールで可視化しやすいようにデータを加工➟BIツールで可視化という流れでdbtを使うことはとても良いユースケースだと思います。ぜひ、SnowsightでもOKですが、他のBIツールと組み合わせてdbtで加工した結果を可視化してみてください!!

次回

Snowflakeをより使いこなそう! Advent Calendar 2021、次回の24日目では、「Snowflake×dbt特有の設定をまとめてみる」というタイトルで執筆します。お楽しみに!