dbt-osmosisを使ったメタデータ入力の軽減
最近業務でデータカタログ関連に携わる機会が多く、その中でカラムやテーブルのディスクリプション(メタデータ)を書くのが結構な手間で悩みの種。。。
どうにか効率よく開発できないか・・・?
ありました!dbt-osmosisを使えばモデルのymlファイルを自動で生成してくれます!
よくあるのが、ディスクリプション書くまでのymlを準備するのが地味にしんどいんですよね〜
と言うことで、やってみる!
dbt-osmosisって?
主な機能として、
- YAML管理自動化
- dbt-power-user for VS Codeなどのツールと統合し、IDEからインタラクティブなクエリやリアルタイムコンパイルを可能にするdbtサーバー
- streamlitベースのワークベンチ
- モデルに対し動的に差分実行
詳しいことは↑のGithubを見てください。
今回はYAML管理の自動化をメインにご紹介します。
dbt-osmosisのインストール
pipでサクッとインストールしちゃいます。
pip3 install dbt-osmosis
依存関係でコケた人はpipxを使ってください。
てか公式はpipx使ってます。。。
dbt_project.ymlにosmosisを定義
dbt_project.ymlにdbt-osmosisを定義してあげることで、どのモデルに対してdbt-osmosisを利用するかを明示的に選択します。
今回はjaffle_shopプロジェクト全体に適用するよう設定しました。
ちなみに、個々のスキーマ毎に設定も可能です。
models:
jaffle_shop:
+dbt-osmosis: "{model}.yml"
materialized: table
staging:
materialized: view
以上で準備が整ったので、早速YAML管理自動化を実施していきます。
YAML管理自動化
冒頭でもお話ししたとおり、メタデータの登録めっちゃめんどくさいですよね。
でもdbt-osmosisを使えば、そんな大変な登録作業がかなり軽減されます。
実際に動かしてみます。
dbtプロジェクトのYAMLファイルを文書化
まずはプロジェクトからYAMLファイルを自動生成する方法を試してみます。
やっぱりYAMLファイルを作成する準備に手間どるので自動生成はありがたい!!
前提として、jaffle_shopのプロジェクトはすでにschema.ymlが存在しています。
YAMLファイルが存在してる場合どのような挙動になるか確認してみます。
YAMLファイルが存在してる場合の挙動
以下コマンドを実行します。
dbt-osmosis yaml document
- YAML ファイルのカラムの順番を変更してデータベースのカラムの順番に合わせる
- データベースに存在するカラムを YAML ファイルに追加する
- データベースに存在しないカラムを YAML ファイルから削除する
- カラムレベルのドキュメントを上流モデルから下流モデルに受け渡す (下流モデルにそのカラムのドキュメントがない場合)
実行すると、元々あったYAMLファイルに追記される形となります。
以下スクショで差分を表示しています。
何が追加されているかと言うと、例えば、stg_customersモデルに存在するカラムがschema.ymlに存在しないので、その部分を追記してくれています。
結果として、すでにYAMLファイルが存在する場合、モデルの中身と比較して、無いものは追加してくれます。
さらに並び順も変えてくれるそうです。
この機能だけでも、手動で作った場合の記載漏れを防止できますね!
YAMLファイルが存在しない場合の挙動
schema.ymlを空にし、以下コマンドを実行します。
dbt-osmosis yaml document
結果として、何も起きませんでした。。。あれ?
はい。どうやら空はダメみたいです。
本来の使い方はschema.ymlに最低限、モデル名まで記載しないとダメみたいです。
こんな感じですね↓
version: 2
models:
- name: customers
モデル名を書いて、再度コマンドを実行すると自動で追記されました。
version: 2
models:
- name: customers
columns:
- name: customer_id
description: ''
- name: first_name
description: ''
- name: last_name
description: ''
- name: first_order
description: ''
- name: most_recent_order
description: ''
- name: number_of_orders
description: ''
- name: customer_lifetime_value
description: ''
ちなみにですが、schema.ymlに間違ったモデル名を書いた場合、もちろん動きませんのでご注意ください。
結果として、元々YAMLファイルがなくても、ファイルを用意してモデル名だけ書いとけばカラム名とディスクリプションは自動で生成してくれます。
これだけもかなり楽になりますね!
YAMLファイルのリファクタリング
dbt-osmosisの構成に基づいて、YAMLファイルをリファクタリングしてくれます。
- dbt_project.yml ファイルの dbt-osmosis var に基づいて、ソースが存在しない場合はブートストラップします。
- dbt_project.ymlファイルに設定されたdbt-osmosis config(理想的には)に基づいて、YAMLファイルを移行します。
- プロジェクトが宣言的な仕様にマッチしていることを確認します (つまり、YAML ファイルが正しい場所にあり、正しい名前を持っていること)。
- YAMLファイルのカラムの並び順をデータベースのカラムの並び順と一致させます。
- データベースに存在するカラムを YAML ファイルに追加する。
- データベースに存在しないカラムをYAMLファイルから削除する
- 上流モデルから下流モデルにカラムレベルのドキュメントを受け渡す (下流モデルにそのカラムのドキュメントがない場合)
YAMLファイルが存在してる場合の挙動
リファクタリングの挙動もファイルがある場合とない場合で検証してみます。
現在のファイル構成(schena.yml)を確認しておきます。
stagingスキーマとmodels配下にschema.ymlが存在している状態です。
ここから以下コマンドを実行します。
dbt-osmosis yaml refactor
すると、以下のようになりました。
もうお分かりのことと思います。
元々あったschema.ymlの中身のモデル毎に、YAMLファイルが作成されました。
しかも、欠損しているカラムの補完までしてくれています。
可読性や管理の面を考えると、一つのYAMLファイルより、モデル毎にYAMLファイルを管理したほうがいいですよね!
YAMLファイルが存在しない場合の挙動
なんと!refactorコマンド方はschema.ymlの中身が空でもリファクタリングされて、カラム名もディスクリプションを自動作成してくれました!
もうこれ、refactorコマンドでいい気がしてきた。。。。
おまけ
dbt-osmosisはメタデータ作成の下準備(YAMLファイルの自動作成)を手伝ってくれました。
それはそれで大変ありがたい事です。
じゃ次は実際にメタデータを入力する処理を楽にする方法を考えたくなりますよね?
その解決策になるか分からないですが、私が結構気に入っている方法があってdbt power userツールにdbt docsを編集する機能が追加されまして、それ使えばいいんじゃね?って思いました。
やり方
以下スクショのように、docsを書く対象のSQLファイルを選択すると、画面下部のターミナル画面の部分に「DOCUMENTATION EDITOR」タブがあり、そこでYAMLファイルのディスクリプションを編集できちゃいます。
適当にディスクリプション書いて、画面下部の「Save documentation」をクリックします。
すると、YAMLファイルに反映されています。
ちなみにdbt power userからのdocs編集はdbt docs generate
は不要でした。
ただdbt power userでの編集は外出しのmdファイルには対応していなっぽいです。
dbt-coverageでメタデータの網羅率をチェックする
作成したメタデータ情報がちゃんと全て書き切れているかチェックすれば、もう何も怖く無いですよね!
dbt-coverageを使えば、その辺りのチェックもできちゃいます!
dbt-coverageは、プロジェクトにドキュメントやテストの不足がないかをチェックする単一のCLIツールです
pip3 install dbt-coverage
dbt docs generate
# dbt-coverage compute doc --cov-report coverage/coverage-doc.json
Coverage report
=====================================================================
main.customers 6/7 85.7%
main.orders 9/9 100.0%
main.raw_customers 0/3 0.0%
main.raw_orders 0/4 0.0%
main.raw_payments 0/4 0.0%
main.stg_customers 0/3 0.0%
main.stg_orders 0/4 0.0%
main.stg_payments 0/4 0.0%
=====================================================================
Total 15/38 39.5%
customersの網羅率を100%にしたいと思います。
customersの全カラムに対してdescriptionを設定
version: 2
models:
- name: customers
description: This table has basic information about a customer, as well as some derived facts based on a customer's orders
columns:
- name: customer_id
description: This is a unique identifier for a customer
tests:
- unique
- not_null
- name: first_name
description: Customer's first name. PII.
- name: last_name
description: Customer's last name. PII.
- name: first_order
description: Date (UTC) of a customer's first order
- name: most_recent_order
description: Date (UTC) of a customer's most recent order
- name: number_of_orders
description: Count of the number of orders a customer has placed
- name: customer_lifetime_value
description: customer_lifetime_value
sources: []
再度、カバレッジチェックを行います。
# dbt-coverage compute doc --cov-report coverage/coverage-doc.json
Coverage report
=====================================================================
main.customers 7/7 100.0%
main.orders 9/9 100.0%
main.raw_customers 0/3 0.0%
main.raw_orders 0/4 0.0%
main.raw_payments 0/4 0.0%
main.stg_customers 0/3 0.0%
main.stg_orders 0/4 0.0%
main.stg_payments 0/4 0.0%
=====================================================================
Total 16/38 42.1%
はい。網羅率100%になりました〜!
osmosisでメタデータ作って、それをdbt-coverageでチェックするこのコラボレーションはアツい!!激アツだ!
Discussion