People Modern Data Stack '22

この記事は、Money Forward Engineering 2 Advent Calendar 2022 2日目の投稿です。

はじめに

わたしはマネーフォワードの人事部門に所属しているエンジニアで、日頃は人事データパイプラインや自動化ツールを開発したりしています。今回はその中でも採用データパイプラインにフォーカスして、その裏側の技術面について軽く振り返ってみたいと思います。

※本記事には頻繁にdbtが登場しますが、ツール解説は割愛させていただきます。詳しくはこちらをご覧ください。

zenn.dev

Data Source Management 🧹

(おおよそ表記揺れとの戦い)

部署と職種の粒度を再定義

利用中のATS(Applicant Trancking System = 俗に言う採用システム)にはラベル機能があります。これはディメンション(データの切り口)を好きなだけ増やせる魔法の杖です。

このラベルに規則性・一貫性を持たせ、表記揺れを防ぐためにかなりの工数を割いてきました。その内の代表的な例が部署ラベルと職種ラベルです。階層構造を持たせて再定義し、ダッシュボード等でドリルダウンが出来るようにしました。

求人 - 部署 - 職種の辞書データを作成&維持管理

前述のラベルとも関連しますが、ATS上に登録されている求人票と、「それはどの部署のどの職種なのか?」という事を紐付ける必要がありました。オープンポジションと呼ばれるような部署未定ポジションや、複数部門同時進行など色んなパターンがあるためです。このデータは日々メンテナンスしており、新しい求人が出る度に部署+職種を紐づけています。

ATSデータ品質をdbtでモニタリング

品質はイタチごっこになりがちであるため、全て目視確認をしていたら日が暮れてしまいます。そこでdbtのテストの登場です。2,3行書くだけでバリデーション貼れるのですから、とてもお手軽です。dbt-utilsとdbt-expectationsとcore純正のものを使用しています。異常値を見つけたらデータソースを直す、あるいはSQLでねじ伏せています。

ここで私の思想を述べたいのですが、Garbage in, Garbage outという有名な言葉がありますが、私はある程度のGarbageは積極的に拾って基盤側でクレンジングするスタンスです。なぜなら皆、データ入力が本業ではないからです。

Extract & Load 🚛

(原始的なやり方が一番よかった)

GitHub Actionsフル活用

基盤を作り始めた初期はAirbyteを使っていました。理由は使い慣れていたからです。ですが途中でやめました。オーバーエンジニアリングであったためです。今はGitHub ActionsでATSからデータを落としてbq loadし、dbt buildしてelementaryの更新とBIのデータ更新のループを全自動で回しています。ビジネスサイドと異なりデータ量が少ないので、これで全くもって問題ありません。ワークフローは小分けしてそれぞれスタンドアロンでworkflow_dispatchで手動実行できるようにしてあります。dbtだけ、elementaryだけ、、、実行したいというケースが多々あるためです。その代わり、

name: hige_workflow

on:
workflow_run:
  workflows:
    - hogehoge
  types:
    - completed

という具合に依存関係を持たせてやっています。ワークフローの本数が少ないので、リネージがなくても混乱しません。あとはPR時などの挙動ですが、それは後ほど記述します。

Workload Identity連携

地味ですが便利です。GCP(触れていませんでしたが、GCPを使っています)のクレデンシャルをGitHubのシークレットに登録しておく必要がなくなりました。

毎朝dbt source freshness

保険みたいなものです。毎日更新されてほしいデータが更新されていなかったら困りますよね?dbt のsouces.ymlで定義したテーブルに対して、「このテーブルが●時間の間、更新されていなかったらエラーを出して」という具合に仕込んでいます。

Transformation 🍳

(データは少ないですが、中身は結構複雑)

ワイドテーブルを採用

ラルフ・キンボール博士の本にも紹介されていましたが、人事データは割とファクトレステーブルになりがちです。想像するとお分かりになると思いますが、INTEGERやFLOATの出番が少ないです。またデータ量も少なく、データを見るツールもスプシやBIです。であればワイドテーブルで良いだろうということで3桁カラムの大福帳を用意しています。そこからデータマートを切り出していくイメージ。

macroで表記揺れ管理

前述のラベルの表記揺れにdbt の macro を使って簡素化していますという話です。macroの大元を1つ変えればそれを参照している多数のモデルも連動して変わるということでmacroに託して楽しています。DRY。

3層モデル

dbtvaultも試しましたが、Too Muchすぎました。結局、source/stage/martのレイヤリングに先祖帰りして今に至ります。これで全然よかった。

Use 🍱

スプシ/BI

スプレッドシート派/ダッシュボード派に分かれると思うので、どちらにも対応できるよう配慮しています。スプシはコネクテッドシート経由で提供しています。ダッシュボードはオペレーションにも使われていて、面接予定リストを表示したり、他にもこれから内製データアプリケーションレベルのものを出そうとしたりしています。何でもできますね。

権限付与もdbtに任せる

テーブルのアクセス権限もdbtに任せています。schema.ymlに

  - name: mart_hoge
    config:
      grants:
        roles/bigquery.dataEditor: ['user:xxxxx@hoge.co.jp', 'user:yyyy@hoge.co.jp']

とでも書いておけば良いです。詳しくはdbt公式ドキュメントをご覧ください。

Development 💻

(dbt CLIでやっています)

elementaryとPiperider

データ監視はelementaryを使っていて、これからPiperiderに変えるか併用するか迷っているところです。どちらも性能は近くて、データ異常検知寄りのものです。個人的にPiperiderに期待していまして、なぜかというとdbt プロジェクトの聖域に土足で上がってこない行儀正しいツールだからです(分かる人には分かる)。スタンドアロンで動くのでDWHのリソースを食いません。単に外から観察して統計量をレポーティングしてくれるものです。それでいいんです。

Docs類はGAE

この記事に書いてあります。 単一htmlファイルさえあれば、なんでもGAEにデプロイして認証つけて公開出来ます。elementaryでもPiperiderでも同様です。

GitHubと社内Wikiを同期

エンジニアじゃない方向けのドキュメントを社内wikiに同期できる素敵なツールが社内公開されており、それを利用しています。GitHubをSSoTにしたい派だけどそうも簡単にはいかないという課題に対する具体的解決策になりました。尚、こちらもGitHub Actionsで動いています。

品質モニタリング用テーブルを用意

「テストで引っかかっても、とりあえず更新したい」という欲があります。それを解決するにはテスト用テーブルを切り出し、そこに対してテストをかければ良いという考えです。トレードオフとして、バグは即修正マストです。

dbt-osmosisYAML自動管理

このPythonライブラリはやばいです。dbt-osmosis yaml refactor と呪文を唱えるとYAMLがいい感じに更新・作成されます。特に上流データモデルのdescriptionをコピーしてくれる点がありがたいです。codegenより強力。devブランチへのPR作成時にこれとsqlfluff(定番なので触れない)を動かしています。

dbt-osmosisのイケてるIDE

引き続きosmosisネタ。dbt-osmosis workbench と打つとstreamlitベースのIDEが起動します。

  1. target切り替え
  2. 自動コンパイル
  3. テスト実行とその結果の統計量が見れる(pandas-profiling)

dbt compile した結果をBigQueryのコンソールにコピペしている方、1万倍早くなりますよ。

Exposuresの利用

最近は若干億劫になってきているのが本音ですが、使っています。ダッシュボードに埋めていますし、なんなら自分も見返すこともあります。何を書いているかといえば、カラムの説明や変換ロジックなどをつらつらと。URLを埋め込めるのですぐジャンプできるのも良いですね。

おしまい

2023年もよろしくお願いします(気が早い)。