G-gen の min です。Google Cloud のデータ変換パイプラインツールである Dataform で、データ品質テストを実装するためのアサーション(assertion)機能について解説します。

概要
Dataform とは
Dataform は、BigQuery 内で SQL を用いたデータ変換パイプラインを開発、テスト、デプロイ、実行するためのフルマネージドなサービスです。
Dataform の基本的な概念や使い方については、以下の記事を参照してください。
アサーションとは
Dataform の アサーション は、データ品質テストをパイプラインに組み込むための機能です。アサーションは、内部的には「指定した条件に違反する行を検出する SELECT クエリ」として実装されます。このクエリが 1 行でもデータを返した場合、つまり条件違反のデータが1件でも存在した場合、そのアサーションは失敗となります。
Dataform はワークフローを実行するたびにアサーションを実行します。アサーションが失敗すると、実行ログに失敗が記録され、後続の処理を停止させたり、アラートを送信したりできます。
アサーションの種類
Dataform のアサーションは、大きく2種類に分けられます。
| 種別 | 説明 | 用途 |
|---|---|---|
| 組み込みアサーション | テーブル定義ファイル(.sqlx)の config ブロック内で宣言的に指定 |
一般的なデータ品質チェック |
| 手動アサーション | 独立した .sqlx に任意の SQL を記述 |
複雑なチェック、複数テーブルの整合性 |
前者の組み込みアサーションは、Dataform に組み込みで用意されたアサーションです。簡単な記述で呼び出すことができます。Dataform には以下の組み込みアサーションが用意されています。
| 名称 | 説明 |
|---|---|
| nonNull | 指定された列に null の行がないことを確認 |
| rowConditions | すべての行が指定した条件を満たすことを確認 |
| uniqueKey | 指定した列で、すべての行の値が一意である(重複した値がない)ことを確認 |
| uniqueKeys | 指定した列の組み合わせで、すべての行の値が一意である(重複した値がない)ことを確認 |
後者の手動アサーションは、ユーザーが独自の SQL クエリを記述することによって定義できるアサーションです。記述した SQL が1行でも値を返すと、アサーションは失敗します。
組み込みアサーションの詳細
nonNull
指定したカラムに NULL 値が含まれていないことを検証します。主キーや必須項目など、NULL であってはならないカラムに対して使用します。
以下の例では、user_id と email カラムに NULL 値が存在しないことをテストします。
config {
type: "table",
assertions: {
nonNull: ["user_id", "email"]
}
}
SELECT
1 AS user_id,
"test@example.com" AS email
なお、BigQuery テーブルには NOT NULL 制約を指定できますが、この制約と nonNull アサーションを混同しないよう注意が必要です。nonNull アサーションは、データパイプラインの実行時に NULL 値がないかをテストする機能です。このアサーションを定義しても、Dataform が作成する BigQuery テーブルのスキーマ自体に NOT NULL 制約が付与されるわけではありません。
Dataform で自動作成されたテーブルのカラムは、デフォルトですべて NULL を許容する(NULLABLE)モードです。スキーマレベルで NULL 値を確実に禁止したい場合は、Dataform の operations を使用して明示的に設定するなど、追加の対応が必要です。
uniqueKey / uniqueKeys
uniqueKey は、指定した単一カラムの値がテーブル内で一意である(重複がない)ことを検証します。uniqueKeys は、指定した複数カラムの組み合わせがテーブル内で一意であることを検証します。
uniqueKeys では複数のカラムセットをテストできます。以下の例では、「user_id の一意性」と「signup_date と customer_id の組み合わせの一意性」の2つの条件をテストします。
config {
type: "table",
assertions: {
uniqueKeys: [
["user_id"],
["signup_date", "customer_id"]
]
}
}
SELECT ...
rowConditions
独自の SQL 条件式を記述して、すべての行がその条件を満たすことを検証します。各条件式は文字列として記述し、テーブルのいずれかの行で条件式が false または NULL を返すと、アサーションは失敗します。
以下の例では、「signup_date が NULL でない場合は 2025-10-01 より後である」かつ「email がメールアドレス形式である」という2つの条件をテストします。
config {
type: "incremental",
assertions: {
rowConditions: [
'signup_date is null or signup_date > "2025-10-01"',
'REGEXP_CONTAINS(email, r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")'
]
}
}
SELECT ...
手動アサーションの詳細
定義方法
手動アサーションは、組み込みアサーションで表現しにくい複雑なロジックや、複数テーブルをまたぐテストに使用します。
手動アサーションを定義するには、config ブロックの type として assertion を指定し、その下にテストしたい条件(違反する行を見つける)の SQL クエリを記述します。
参照整合性のチェック例
例えば、users テーブルと orders テーブルで、存在しない user_id が orders テーブルに含まれていないか(参照整合性)をテストする手動アサーションは以下のようになります。このクエリは、orders テーブルに存在する user_id が users テーブルに存在しない行を検出します。
-- definitions/assertions/check_order_user_id.sqlx config { type: "assertion" } SELECT o.order_id FROM ${ref("orders")} AS o LEFT JOIN ${ref("users")} AS u ON o.user_id = u.user_id WHERE u.user_id IS NULL
集計値のチェック例
手動アサーションは、集計値に対するテストも定義できます。例えば、日別の売上データ(daily_sales)に、マイナスの売上日が存在しないことを確認するアサーションは以下のように記述できます。
-- definitions/assertions/check_negative_revenue.sqlx config { type: "assertion" } SELECT sale_date FROM ${ref("daily_sales")} WHERE total_revenue < 0
アサーションの依存関係の制御
すべての依存先アサーションを待機
アサーション失敗時に後続処理を止めたい場合は、依存関係を制御します。
デフォルト設定では、アサーションが失敗しても、そのテーブルを参照する後続の処理は実行されます。
config ブロックで dependOnDependencyAssertions: true を設定すると、このアクション(テーブル作成などの処理)が依存するすべてのアクションに定義されたアサーションが成功するまで、処理の実行は開始されません。
-- table_B.sqlx config { type: "table", dependOnDependencyAssertions: true } -- table_A のアサーションがすべて成功しないと、table_B の作成は開始されない SELECT * FROM ${ref("table_A")}
特定の依存アクションのアサーションのみ待機
dependencies パラメータで依存アクションを指定する際に includeDependentAssertions: true を設定することで、特定の依存アクションのアサーションのみを待機させることができます。
以下の例では、table_C は table_A と table_B に依存していますが、table_B のアサーションが成功した場合にのみ、処理が実行されます(table_A のアサーション成否は問いません)。
-- table_C.sqlx config { type: "table", dependencies: [ "table_A", {name: "table_B", includeDependentAssertions: true} ] } SELECT * FROM ${ref("table_A")} LEFT JOIN ${ref("table_B")} ON ...
特定のアサーションのみを依存先に指定
さらに細かく、特定のアクションの特定の組み込みアサーションや手動アサーションのみを依存関係に設定することもできます。アサーション名は アクション名_assertions_アサーション種別_インデックス という命名規則で付けられています。手動アサーションの場合は、ファイル名がそのままアサーション名になります。
-- table_B.sqlx config { type: "table", dependencies: [ "table_A_assertions_uniqueKey_0", -- table_A の uniqueKey アサーション "check_order_user_id" -- 手動アサーション ] } SELECT * FROM ${ref("table_A")}
実行結果の確認と通知
実行結果の確認
Dataform のワークフロー実行ログから、各アサーションが成功したか失敗したかを確認できます。

アサーション失敗時の通知
アサーションが失敗した場合、Dataform は Cloud Logging にログを自動的に出力します。このログをトリガーとして、Cloud Monitoring でログベースのアラートを設定することで、アサーション失敗時に通知を送信できます。
失敗したワークフロー呼び出しに対するアラート設定の詳細は、公式ドキュメントをご参照ください。
佐々木 愛美 (min) (記事一覧)
クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。
