FindyにおけるDataformの活用とその効果

こんにちは。 2024/05よりファインディ株式会社にデータエンジニアとして入社した田頭(tagasyksk)です。本記事では、データ変換サービスであるDataformについてその活用方法や導入後の効果についてご紹介します。

弊社では、現在次のような構成でデータ基盤を構成しており、BigQuery内でのデータ変換にDataformを利用しています。

この構成を踏まえてご覧いただければ幸いです。それでは見ていきましょう!

Dataformについて

サービスの説明については、公式ドキュメントを引用します。

Dataform は、データ アナリストが BigQuery でデータ変換を行う複雑な SQL ワークフローを開発、テスト、バージョン管理、スケジュール設定するためのサービスです。

例えば、

  • BigQueryでスケジュール実行しているSQLをGit管理したい
  • 依存関係のあるSQLを順番に実行してほしい
  • クエリの実行結果が意図した挙動を行うかどうかをテストしたい

というようなタイミングで活用できます。

導入の背景

Dataform導入前の課題点として、SpreadsheetやGASから利用されているクエリを管理できていませんでした。その結果、利用者が想定しているデータと実際にクエリで取得しているデータが異なっていたり、正しくないテーブルを参照しているケースが発生していました。

このような背景のもと、次のメリットを踏まえてDataformを導入しました。

データ基盤に必要な機能が揃っており、簡単に運用を始められること

Dataformは無料でありながら、次のようなデータ基盤に必要な機能が揃っています。

  • 依存関係を定義してDAGを構成できる
  • 特定のタグが付与されたテーブルでワークフローを構成できる
  • データリネージを可視化できる
  • Gitと連携してクエリ管理ができる
  • Google CloudのIAMでカラム単位での権限制御ができる

Google Cloudのマネージドサービスなので、余計なメンテナンスをする必要もありません。

クエリ作成のハードルが非常に低いこと

ソフトウェア開発の経験がないアナリストやBizサイドにとって、データ基盤への学習コストが低いことは非常に重要です。

Dataformでは.sqlxというSQLを拡張したファイル形式でクエリを開発します。

config {
    type: "table",
    "schema": "stg_hoge",
    "tags": [
        "stg_hoge"
    ],
    "description": "ユーザー",
    "columns": {
        "id": "",
        "user_name": "ユーザー名",
        "created_at": "作成日",
        "updated_at": "更新日",
    },
    "assertions": {
        "nonNull": [
            "id",
            "user_name",
            "created_at"
        ],
        "uniqueKey": [
            "id"
        ]
    }
}

SELECT
    id,
    user_name,
    created_at,
    updated_at
FROM
    ${ref("lake_hoge", "users")}

sqlxは普通のSQLとdescriptionやassertionを含む簡単なconfigで作成可能なので、学習コストが非常に低いです。

Gitを用いたクエリ管理に関しても、Dataform側がバックエンドで行ってくれます。ブラウザ内でクエリ開発からPR作成までが完結するため、Gitのコマンドを覚える必要がありません。

導入後の効果

Dataform導入によって、Bizサイドが作成したクエリをアナリスト・データエンジニアが適切にレビューできるようになりました。 mart層のモデルの数もDataform導入後約4倍となり、開発が活発になっていることが分かります。

また、社内メンバーにDataformの利点について聞いてみたところ、次のような声も聞きました。

  • 1モデルあたり1ファイルの作成で済むので、開発の負担が減った
  • 実行ログをDataformコンソール上で確認できるので、BigQueryと実行ログの横断が楽になった

FindyでのDataform運用

ここからはDataformを運用していく上でどのような課題が生じ、どのように解決しているかを詳しく書いていきます。

導入しての課題

Dataform導入当初は、次のようなフローでクエリを開発していました。

データ基盤を運用していく中で、次の課題が生じました。

  • Production環境にあるテーブルに対してワークスペースからモデルを実行できてしまう

    Dataformのコンソール画面上から、まだレビューしていないモデルを実行できてしまうのは、意図しないスキーマの変換やデータ変換のバッティングが起きてしまいます。データエンジニア側としても望ましい状態ではありませんでした。

  • 新しいワークフロー用のタグの追加忘れが頻発した

    Dataformではsqlx内に記述するタグを指定してワークフローを構成します。ワークフローの管理はTerraformで行っていたため、Dataform側のPRからはタグが追加されているか分からず、データ更新時にタグの追加忘れが発覚することがありました。

  • テーブル変更時、影響範囲が不透明でレビューしづらい

    クエリを修正する際、修正したテーブルがどのテーブルから参照されているかを確認できていませんでした。計算ロジックの変更がどのテーブルに伝播するのか分からず、レビューが不十分なままマージされてしまうことがありました。

改善点

クエリ開発フローを次のように変更しました。

緊急対応以外の開発は全てdevelop環境で行なうように取り決め、リリース作業を導入しました。また、CIパイプラインの中で次のような項目を自動でチェックし、事故を防止しています。

  • 変更されたsqlxファイルを検出し、クエリとAssertionをDevelop環境で自動実行
  • 変更モデルに依存しているテーブルを検出し、PR上に表示

    dataform compileで取得してきたjsonをパースし、変更ファイルのテーブルを検索することで検出しています。

      - name: Detect Referenced Table
        run: |
          DIFF_FILES=$(echo "${{ steps.get_change_files.outputs.diff_files }}")
          echo "referenced_tables<<EOF" >> $GITHUB_OUTPUT
          for file in $DIFF_FILES; do
            dataset=$(jq -r ".tables[] | select(.fileName == \"$file\") | .canonicalTarget.schema" definition.json)
            table=$(jq -r ".tables[] | select(.fileName == \"$file\") | .canonicalTarget.name" definition.json)
            referenced_tables=$(cat definition.json | jq -r ".tables[] | select(.dependencyTargets[]?.schema? == \"$dataset\" and .dependencyTargets[]?.name? == \"$table\") | .canonicalTarget | .schema+\".\"+.name" | awk '!a[$0]++')
            echo "**$file**" >> $GITHUB_OUTPUT
            echo "$referenced_tables" >> $GITHUB_OUTPUT
          done
          echo "EOF" >> $GITHUB_OUTPUT
  • 開発に利用したワークスペースを自動で削除する
  • Dataform CLIのdry-runでProductionの依存テーブルに問題が無いか確認1

  • ワークフローで付与されているタグとsqlxファイル上で付与されているタグを比較し、ワークフローに無いタグをリリースPRで表示

    ワークフロー構成で利用されているタグは、Google Cloud側から提供されているAPIで取得できます。

    cloud.google.com

    APIで取得したタグとsqlxに付与されているタグを突合し、ワークフローに追加し忘れたタグが無いか確認しています。追加忘れが見つかった場合は、Terraformで管理しているリリース構成に新しいタグを追加して対応しています。

以上のような改善活動の結果、データの更新漏れやエラーが減りました。アラート対応が減ったことで、データエンジニアが他の業務に時間を割けるようになりました。 リリース導入前後でアラート数を集計してみたのですが、導入前1ヶ月のワークフローで生じたエラーは54件なのに対し、リリース導入後1ヶ月では25件と半分以下になっていました。

今後の展望

データの品質向上

クエリのレビュー体制を整えることができましたが、クエリやデータの品質にはまだ課題を残しています。

GASやスプレッドシート内で発行されていたクエリをDataformの管理下に置くことはできましたが、DRYの原則に反していたり、可読性に課題のあるクエリがまだ存在しています。

データ品質については、異常なデータを検知してアラートを出す仕組みが整える必要があります。Dataformではassertionやtestといった形式でテストを書くことができますが、現状はデフォルトでサポートされているassertion(nullチェックやuniqueKeyなど)を組み込んでいる程度です。

これからも社員が増えていくことが予想される中で、データ品質をどうやって維持・向上していくかはこれからも模索していきたいです。

データモデリング

データ利用者がスムーズに分析を進めていくために、データモデリングは必要不可欠です。しかし、弊社ではモデリングに精通した人材がいないのが現状です。

5月からデータエンジニアとアナリストで定期的に集まってデータモデリングの勉強会を行い、チーム内のナレッジを揃えながら少しずつクエリの見直しを進めています。

※一緒にデータモデリングをしていきたい方がいましたら、是非カジュアル面談にご応募ください!データモデリングを一緒にやっていきましょう!

終わりに

いかがでしたでしょうか?今回は弊社でのDataformの活用について書きました。

弊社ではデータ基盤を共に育てていくメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております!

herp.careers

herp.careers


  1. Dataform CLIがver3.0未満だとdry-runで検証できるのはDataform内での依存関係やテーブルの有無のみで、declarationで宣言したデータソースがBigQuery上に存在しない場合などでエラーが起きません。(最近のリリースで出来るようになったみたいですが、Dataform CLIのver3.0以上はbreaking changeが多いのでまだ試せていません...)現状は、データソースを参照するようなクエリはリリース時に目視チェックすることでカバーしています。