テーブルの作成

Dataform では、テーブルはワークフローを構成するオブジェクトの種類の一つです。ワークフロー用に宣言されたデータソースまたはワークフロー内の他のテーブルからデータを参照するテーブルを作成できます。Dataform は、テーブル定義をリアルタイムで SQL にコンパイルします。実行をトリガーすると、Dataform は SQL コードを実行し、BigQuery で定義済みテーブルを作成します。

type: "table" SQLX ファイルでは、次のテーブルタイプを作成できます。

  • table: 通常のテーブル。
  • incremental: 増分テーブル。
  • view: テーブルビュー。詳細については、ビューの概要をご覧ください。

テーブルのパーティションとクラスタを定義することもできます。

テーブルの目的や、ワークフロー内の他のテーブルとの関係を記録するには、テーブルまたは選択した列にドキュメントを追加します。

テーブル内のデータを特定の条件に対してテストするには、アサーションと呼ばれるデータ品質テストクエリを作成します。 Dataform は、ワークフローを更新するたびにアサーションを実行し、アサーションが失敗した場合にアラートを送信します。

選択したテーブルのデフォルトのスキーマ、データベース、名前をオーバーライドするには、テーブル設定をオーバーライドします。

テーブルの作成を無効にする、またはテーブルの作成前または作成後に SQL ステートメントを実行するには、追加のアクションを構成します。

実行後に BigQuery でテーブルを整理するには、BigQuery ラベルを追加します。詳細については、ラベルの概要をご覧ください。

テーブル列レベルでデータアクセスを制限するには、BigQuery ポリシータグを追加します。詳細については、列レベルのアクセス制御の概要をご覧ください。

外部システムによって適用された BigQuery のデータポリシーとデータ ガバナンス タグ(プレビュー)をテーブルの実行全体で保持するには、アクセス制御メタデータを保持します。

type: "table" SQLX ファイルでテーブルを定義するだけでなく、type: "operations" SQLX ファイルでカスタム SQL クエリを定義することで、空のテーブルを作成できます。 別のサービスでデータを入力できるように、空白のテーブルを作成することもできます。

始める前に

  1. Google Cloud コンソールで、[Dataform] ページに移動します。

    Dataform に移動

  2. リポジトリで開発ワークスペースを作成して初期化します。

  3. 省略可: データソースを宣言する。

必要なロール

このドキュメントのタスクを実行するために必要な権限を取得するには、次の IAM ロールを付与するように管理者へ依頼してください。

  • ワークスペースに対する Dataform 編集者(roles/dataform.editor)
  • メタデータを Knowledge Catalog に同期するには: プロジェクトまたは @bigquery エントリ グループに対する Dataplex Catalog 編集者(roles/dataplex.catalogEditor)

ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

アクセス制御メタデータを保持するには、Dataform ワークフローを実行するサービス アカウントに、タスクに応じて特定の IAM 権限が必要です。

  • メタデータを抽出する: INFORMATION_SCHEMA.COLUMNS ビューを読み取るには、サービス アカウントにデータセットまたはテーブル スキーマの読み取り権限が必要です。これらの権限は、次の IAM ロールに含まれています。

  • データ ガバナンスタグを適用する: テーブルとビューにデータ ガバナンスタグを適用して管理するには、サービス アカウントに bigquery.tables.createTagBinding 権限と bigquery.tables.deleteTagBinding 権限が必要です。これらの権限は、次の IAM 事前定義ロールに含まれています。

  • データポリシーを適用する: データポリシー(タグなしポリシーを含む)を作成して更新するには、サービス アカウントに bigquery.dataPolicies.create 権限と bigquery.dataPolicies.update 権限が必要です。これらの権限は、次の IAM 事前定義ロールに含まれています。

テーブルを作成する

このセクションでは、Dataform で Dataform コアを使用してテーブルを作成する方法について説明します。

テーブル定義について

テーブルを定義するには、テーブルタイプを定義し、type: "table" SQLX ファイルに SELECT ステートメントを記述します。次に、Dataform は、Dataform コアのコードを SQL にコンパイルして SQL コードを実行し、BigQuery で定義済みテーブルを作成します。

Dataform コアの SELECT ステートメントでは、テーブル構造を定義して、ワークフローの他のオブジェクトを参照します。

type: "table" SQLX ファイルでテーブルを定義するだけでなく、type: "operations" SQLX ファイルでカスタム SQL クエリを定義することで、空のテーブルを作成できます。 詳細については、空のテーブルを作成するをご覧ください。

ref を使用して依存関係を参照する

SELECT ステートメントでワークフロー アクションを参照し、依存関係として自動的に追加するには、ref 関数を使用します。Dataform は、正しいパイプラインの順序を検証するため、テーブルに依存するテーブルの前に依存関係を実行します。

ref 関数は、Dataform の依存関係管理に不可欠な Dataform コアの組み込み関数です。ref 関数を使用すると、スキーマ名とテーブル名をハードコードする代わりに、Dataform ワークフローで定義された次のオブジェクトを参照して自動的に依存できます。

Dataform は、ref 関数を使用して、作成または更新するすべてのテーブルの依存関係ツリーを構築します。

コンパイル後、Dataform は CREATE、REPLACE、INSERT、MERGE などの定型ステートメントを SQL ステートメントに追加します。

次のコードサンプルは、ref 関数を使用したテーブル定義を示しています。

config { type: "table" }

SELECT
  order_date AS date,
  order_id AS order_id,
  order_status AS order_status,
  SUM(item_count) AS item_count,
  SUM(amount) AS revenue

FROM ${ref("store_clean")}

GROUP BY 1, 2

ref 関数で、依存するテーブルまたはデータソース宣言の名前を指定します。通常、これはテーブルまたはデータソース宣言が定義されている SQLX ファイルのファイル名です。

テーブル名がオーバーライドされている場合は、ref 関数でオーバーライドされた名前を使用します。 たとえば、config { name: "overridden_name" } を ref("overridden_name") としてテーブルを参照します。詳細については、テーブル設定をオーバーライドするとオーバーライドされたテーブル名でテーブルを参照するをご覧ください。

異なるスキーマに同じ名前のテーブルが複数ある場合は、ref 関数にスキーマ名とテーブル名の 2 つの引数を指定して、特定のテーブルを参照できます。

次のコードサンプルは、特定のスキーマ内のテーブルを指定する 2 つの引数を持つ ref 関数を示しています。

config { type: "table" }
SELECT * FROM ${ref("schema", "store_clean")}

また、SELECT ステートメントの ref 関数で参照されていないテーブル、アサーション、データソース宣言、またはカスタム SQL オペレーションの config ブロックにテーブルの依存関係を手動で追加することもできます。Dataform は、従属テーブルの前にこれらの依存関係を実行します。

次のコードサンプルは、config ブロック内のテーブル依存関係を示しています。

config { dependencies: [ "unreferenced_table" ] }
SELECT * FROM ...

ワークフローでの依存関係の管理の詳細については、依存関係を設定するをご覧ください。

resolve を使用して他のテーブルを参照する

resolve 関数を使用すると、ref 関数のように SELECT ステートメントでテーブルまたはデータソースの宣言を参照できますが、参照は依存関係として追加されません。つまり、resolve 関数を使用して参照されるオブジェクトは、resolve 関数を使用するテーブルの実行に影響しません。

組み込みの Dataform コア関数の詳細については、Dataform コアのリファレンスをご覧ください。

テーブル定義用の SQLX ファイルを作成する

テーブル定義 SQLX ファイルを definitions/ ディレクトリに保存します。definitions/ ディレクトリに新しい SQLX ファイルを作成する手順は次のとおりです。

  1. Google Cloud コンソールで、[Dataform] ページに移動します。

    Dataform に移動

  2. リポジトリを開くには、リポジトリ名をクリックします。

  3. 開発ワークスペースを開くには、ワークスペース名をクリックします。

  4. [ファイル] ペインで、definitions/ の横にある [その他] をクリックします。

  5. [ファイルを作成] をクリックします。

  6. [ファイルパスを追加] フィールドに、ファイルの名前の後に definitions/ の後に .sqlx を入力します。例: definitions/my-table.sqlx。

    ファイル名 には数字、英字、ハイフン、アンダースコアのみを使用できます。

  7. [ファイルを作成] をクリックします。

テーブルタイプを定義する

新しいテーブルタイプ定義を作成する手順は次のとおりです。

  1. 開発ワークスペースの [ファイル] ペインで definitions/ ディレクトリを開きます。
  2. 編集するテーブル定義 SQLX ファイルを選択します。
  3. このファイルに次のコード スニペットを入力します。

    config { type: "TABLE_TYPE" }
    

    TABLE_TYPE は、次のいずれかのテーブルタイプに置き換えます。

    • table
    • incremental
    • view
  4. 省略可: マテリアライズド ビューを定義するには、type: "view" で次の形式で materialized プロパティを入力します。

    config {
      type: "view",
      materialized: true
    }
    

    詳細については、ITableConfig をご覧ください。

  5. 省略可: [書式] をクリックします。

テーブルの構造と依存関係を定義する

テーブル定義の SELECT ステートメントを記述し、テーブルの構造と依存関係を定義する手順は次のとおりです。

  1. 開発ワークスペースの [ファイル] ペインで definitions/ ディレクトリを開きます。
  2. 編集するテーブル定義 SQLX ファイルを選択します。
  3. config ブロックの下に、SELECT ステートメントを記述します。
  4. 省略可: [書式] をクリックします。

次のコードサンプルは、SELECT ステートメントと ref 関数を含むテーブル定義を示しています。

config { type: "table" }
SELECT
  customers.id AS id,
  customers.first_name AS first_name,
  customers.last_name AS last_name,
  customers.email AS email,
  customers.country AS country,
  COUNT(orders.id) AS order_count,
  SUM(orders.amount) AS total_spent
FROM
  dataform-samples.dataform_sample.crm_customers AS customers
  LEFT JOIN ${ref('order_stats')} orders
    ON customers.id = orders.customer_id

WHERE
  customers.id IS NOT NULL
  AND customers.first_name <> 'Internal account'
  AND country IN ('UK', 'US', 'FR', 'ES', 'NG', 'JP')

GROUP BY 1, 2, 3, 4, 5

列スキーマの制限を緩和する

type: "table" または type: "incremental" SQLX ファイルでテーブルを定義すると、Dataform は明示的な列スキーマ定義リストなしで、SELECT クエリを BigQuery の CREATE OR REPLACE TABLE ... AS SELECT ステートメントにコンパイルします。その結果、BigQuery はデフォルトで NULLABLE モードで列を作成します。

Dataform テーブル定義では、config ブロックまたは columns プロパティで列のモードを REQUIRED(NOT NULL)に設定することはできません。BigQuery では、明示的なスキーマ定義でテーブルを再作成せずに、既存の列のモードを NULLABLE から REQUIRED に変更することもできません。BigQuery で列モードを変更する方法については、列のモードを変更するをご覧ください。

null 以外の値を検証するか、REQUIRED 列を含むテーブルを作成するには、次のいずれかの方法を使用します。

アサーションで非 null 値を検証する
テーブルの config ブロックに、assertions: { nonNull: ["column_name"] } や assertions: { rowConditions: ["column_name IS NOT NULL"] } などの組み込みの nonNull または rowConditions アサーションを追加します。別の type: "assertion" SQLX ファイルで手動アサーションを定義することもできます。アサーションは、基盤となる BigQuery 列モードを NULLABLE から REQUIRED に変更することなく、ワークフローの実行中に行に NULL 値が含まれていないことを確認します。アサーションの詳細については、アサーションを使用してデータをテストするをご覧ください。
カスタム SQL オペレーションまたは BigQuery で NOT NULL 列を定義する
BigQuery スキーマで列を REQUIRED モードに設定するテーブルを作成するには、config { type: "operations", hasOutput: true } を使用してカスタム SQL オペレーション ファイルに明示的な NOT NULL 列制約を含む CREATE OR REPLACE TABLE DDL ステートメントを記述するか、BigQuery でテーブル スキーマを直接作成して管理します。DDL ステートメントで REQUIRED 列を定義する方法については、REQUIRED 列を含むテーブルの作成をご覧ください。

手動テーブルの依存関係を追加する

SELECT ステートメントで参照されていないものの、現在のテーブルの前に実行する必要があるテーブルの依存関係を追加するには、次の手順を行います。

  1. 開発ワークスペースの [ファイル] ペインで definitions/ ディレクトリを開きます。
  2. 編集するテーブル定義 SQLX ファイルを選択します。
  3. テーブルの config ブロックに、次のコード スニペットを入力します。

    dependencies: [ "DEPENDENCY_TABLE", ]
    

    DEPENDENCY_TABLE は、依存関係として追加するテーブルのファイル名に置き換えます。複数のファイル名を入力できます。

  4. 省略可: [書式] をクリックします。

次のコードサンプルは、テーブル定義ファイルの config ブロックに手動のテーブル依存関係として追加される 2 つのテーブルを示しています。

config { dependencies: [ "some_table", "some_other_table" ] }

テーブル設定をオーバーライドする

選択したテーブルのデフォルトのスキーマ、データベース、名前をオーバーライドできます。

デフォルトでは、テーブルは workflow_settings.yaml で設定したスキーマとデータベースの構成に従います。テーブルの名前は、テーブル定義 SQLX ファイルの名前と同じです。

選択したテーブルのスキーマと名前をオーバーライドする手順は次のとおりです。

  1. 開発ワークスペースに移動します。

  2. [ファイル] ペインで definitions/ を展開します。

  3. SQLX テーブル定義ファイルを開きます。

  4. このファイルに次のコード スニペットを入力します。

     {
       schema: "OVERRIDDEN_SCHEMA",
       database: "OVERRIDDEN_DATABASE",
       name: "OVERRIDDEN_NAME"
     }
    

    次のように置き換えます。

    • OVERRIDDEN_SCHEMA: テーブルを作成する BigQuery データセット。

    • OVERRIDDEN_DATABASE: テーブルを作成する BigQuery プロジェクトの ID。

    • OVERRIDDEN_NAME: テーブルの名前。SQLX テーブル定義ファイル名とは異なります。

  5. 省略可: [書式] をクリックします。

詳細については、オーバーライドされたテーブル名でテーブルを参照するをご覧ください。

Apache Iceberg マネージド テーブルを作成する

Dataform を使用して、Iceberg テーブル形式で BigQuery テーブルを作成します。これらのテーブルは Iceberg マネージド テーブルと呼ばれます。必要なロールやその他の設定タスクの詳細については、Iceberg マネージド テーブル ワークフローの始める前にの手順をご覧ください。

Iceberg テーブル定義を作成する

テーブルを作成するには、テーブル定義ファイルの bigquery ブロックで Iceberg 構成を定義します。

テーブルを定義する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. テーブル定義 SQLX ファイルを開きます。
  4. config ブロックに、次の形式で iceberg ブロックを含む bigquery ブロックを追加します。

    config {
      type: "table",
      name: "my_table",
      uniqueKey: ["uniquekey"],
      bigquery: {
        iceberg: {
          bucket_name: "BUCKET_NAME"
        }
      }
    }
    

    BUCKET_NAME は、テーブルデータが保存されている Cloud Storage バケットの名前に置き換えます。

    その他のプロパティは省略可能で、指定しない場合はデフォルト値が使用されます。詳細については、iceberg プロパティをご覧ください。

    各テーブルの値を指定するか、workflow_settings.yaml でワークフロー レベルのデフォルトを設定できます。iceberg ブロックでプロパティを明示的に設定することで、ワークフロー レベルのデフォルトをオーバーライドできます。

テーブル パーティションとクラスタを作成する

このセクションでは、Dataform コアを使用してテーブル パーティションとクラスタを作成する方法について説明します。BigQuery は、パーティション分割テーブルとテーブル クラスタリングをサポートしています。詳細については、パーティション分割テーブルの概要とクラスタ化テーブルの作成と使用をご覧ください。

テーブル パーティションを作成する

テーブル パーティションを作成するには、次の手順に沿って操作します。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. テーブル定義 SQLX ファイルを開きます。
  4. config ブロックで、テーブルタイプの宣言の下に次の形式で bigquery ブロックを追加します。

    config {
      type: "table",
      bigquery: {
      }
    }
    
  5. この bigquery ブロックに次のコード スニペットを入力します。

        partitionBy: "PARTITION_EXPRESSION"
    

    PARTITION_EXPRESSION は、テーブルをパーティショニングする式に置き換えます。

  6. 省略可: [書式] をクリックします。

次のコードサンプルは、テーブル定義 SQLX ファイルでの 1 時間ごとのテーブル分割を示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "DATETIME_TRUNC(<timestamp_column>, HOUR)"
  }
}

次のコードサンプルは、テーブル定義 SQLX ファイルでの整数値によるテーブル分割を示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "RANGE_BUCKET(<integer_column>, GENERATE_ARRAY(0, 1000000, 1000))"
  }
}

パーティション フィルタを設定する

パーティション フィルタを設定する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. パーティション分割テーブルの定義 SQLX ファイルを開きます。
  4. この bigquery ブロックに次のコード スニペットを入力します。

    requirePartitionFilter : true
    
  5. 省略可: [書式] をクリックします。

次のコードサンプルは、パーティション分割テーブル SQLX ファイルの bigquery ブロックに設定されたパーティション フィルタを示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "DATE(ts)",
    requirePartitionFilter : true
  }
}
SELECT CURRENT_TIMESTAMP() AS ts

BigQuery のパーティション フィルタの詳細については、パーティション分割テーブルのパーティション フィルタ必須属性の設定をご覧ください。

パーティションの保持期間を設定する

パーティション分割テーブル内のすべてのパーティションの保持を制御する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. パーティション分割テーブルの定義 SQLX ファイルを開きます。
  4. この bigquery ブロックに次のコード スニペットを入力します。

    partitionExpirationDays: NUMBER_OF_DAYS
    

    NUMBER_OF_DAYS は、パーティションを保持する日数に置き換えます。

  5. 省略可: [書式] をクリックします。

次のコードサンプルは、パーティション分割テーブル SQLX ファイルの bigquery ブロックで、14 日に設定されたパーティションの保持期間を示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "DATE(ts)",
    partitionExpirationDays: 14,
  }
}
SELECT CURRENT_TIMESTAMP() AS ts

テーブル クラスタを作成する

テーブル クラスタを作成するには、次の手順に沿って操作します。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. テーブル定義 SQLX ファイルを開きます。
  4. この bigquery ブロックに次のコード スニペットを入力します。

        clusterBy: ["CLUSTER_COLUMN"]
    

    CLUSTER_COLUMN は、テーブルをクラスタ化する列の名前に置き換えます。詳細については、clustering_column_list をご覧ください。

  5. 省略可: [書式] をクリックします。

次のコードサンプルは、name 列と revenue 列でクラスタ化されたパーティション分割テーブルを示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "DATE(ts)",
    clusterBy: ["name", "revenue"]
  }
}
SELECT CURRENT_TIMESTAMP() as ts, name, revenue

増分テーブルを構成する

このセクションでは、Dataform コアを使用して増分テーブルを構成する方法について説明します。

増分テーブルについて

Dataform は、テーブルタイプに応じて異なる方法でテーブルを更新します。テーブルまたはビューの実行ごとに、Dataform はテーブルまたはビュー全体を最初から再構築します。

増分テーブルを定義すると、Dataform は初回のみ増分テーブルをゼロから作成します。後続の実行では、Dataform は構成した条件に従って、新しい行のみを増分テーブルに挿入またはマージします。

Dataform は、増分テーブルにすでに存在する列にのみ新しい行を挿入します。新しい列を追加するなどして、増分テーブル定義クエリを変更する場合、テーブルを最初から再構築する必要があるかどうかを判断する必要があります。テーブルを再構築するには、次回テーブルの実行をトリガーするときに、[フル更新で実行] オプションを選択します。その他のオプションについては、フル更新なしで増分テーブル スキーマを変更するをご覧ください。

増分テーブルの一般的なユースケースを次に示します。

パフォーマンスの最適化
ウェブログや分析データなど、一部のデータについては、テーブル全体を再処理するのではなく、新しいレコードのみを処理することをおすすめします。
遅延の軽減
増分テーブルを使用すると、ワークフローを迅速かつ頻繁に実行して、出力テーブルの下流のレイテンシを短縮できます。
日次スナップショット
増分テーブルを構成して、テーブルデータの日次スナップショットを作成できます。たとえば、本番環境のデータベースに格納されているユーザー設定の長期的な分析を行う場合などです。

増分テーブルの行のサブセットを処理する

各実行中に Dataform が処理する行のサブセットを決定するには、増分テーブルの SQLX 定義ファイルに条件付き WHERE 句を追加します。WHERE 句では、増分条件と非増分条件を指定できます。Dataform は、フル更新なしのテーブル実行中に増分条件を適用し、フル更新ありの実行中に非増分条件を適用します。

増分テーブルを構成する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. 増分テーブル定義の SQLX ファイルを開きます
  4. WHERE 句を次の形式で入力します。

    config { type: "incremental" }
    
    SELECT_STATEMENT
    
    ${when(incremental(), `WHERE INCREMENTAL_CONDITION`, `WHERE NON_INCREMENTAL_CONDITION`) }
    

    以下を置き換えます。

    • SELECT_STATEMENT: テーブルを定義する SELECT ステートメント。
    • INCREMENTAL_CONDITION: WHERE 句で指定する条件。フル更新なしでテーブルの実行中に Dataform が処理する行を選択します。
    • NON_INCREMENTAL_CONDITION: フル更新でテーブルの実行中に Dataform が処理する行を選択するために WHERE 句で指定する条件。
  5. 省略可: [書式] をクリックします。

次のコードサンプルは、productiondb.logs テーブルの行をインクリメントに処理する増分テーブルを示しています。

config { type: "incremental" }

SELECT timestamp, message FROM ${ref("productiondb", "logs")}

${when(incremental(),
   `WHERE date > (SELECT MAX(date) FROM ${self()}) AND country = "UK"`,
   `WHERE country = "UK"`)}

次のコードサンプルは、productiondb.customers テーブルのスナップショットを作成する増分テーブルを示しています。

config { type: "incremental" }

SELECT CURRENT_DATE() AS snapshot_date, customer_id, name, account_settings FROM ${ref("productiondb", "customers")}

${when(incremental(), `WHERE snapshot_date > (SELECT MAX(snapshot_date) FROM ${self()})`) }

増分テーブルの行を結合する

増分テーブルに、選択した列の組み合わせに対応する行が 1 つだけ含まれていることを確認するには、選択した列を uniqueKey として設定し、同じ uniqueKey 値を持つ行を結合します。テーブルを更新するときに、Dataform は同じ uniqueKey 値を持つ行を追加するのではなく、マージします。

増分テーブルでマージを構成する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. 増分テーブル定義の SQLX ファイルを選択します
  4. config ブロックで、選択した列を次の形式で uniqueKey として設定します。

    uniqueKey: ["COLUMN_NAME"]
    

    COLUMN_NAME は、選択した列の名前に置き換えます。

  5. 省略可: [書式] をクリックします。

次のコードサンプルは、transaction_id 列を uniqueKey として設定した増分テーブルを示し、常に 1 行が含まれることを確認します。

config {
  type: "incremental",
  uniqueKey: ["transaction_id"]
}

SELECT timestamp, action FROM weblogs.user_actions
${ when(incremental(), `WHERE timestamp > (SELECT MAX(timestamp) FROM ${self()})`) }

増分テーブルの行をフィルタする

増分パーティション分割テーブルで、Dataform がテーブル全体をスキャンして一致する行を検索しないようにするには、レコードのサブセットのみを考慮するように updatePartitionFilter を設定します。

次のサンプルコードは、updatePartitionFilter プロパティと uniqueKey プロパティによってマージ処理が設定された増分パーティション分割テーブルを示しています。このテーブルでは、2 つの異なるタイプのフィルタリングが使用されています。

  • updatePartitionFilter プロパティを使用したターゲット プルーニング: MERGE オペレーション中にターゲット テーブルでスキャンされるパーティションを制限して、uniqueKey に一致する行を検索します。
  • WHERE 句を使用したソースのプルーニング: 増分実行中にソーステーブルから取得される行を制限します。これは ${when(incremental(), ...)} 関数を使用することで実現できます。
config {
  type: "incremental",
  uniqueKey: ["transaction_id"],
  bigquery: {
    partitionBy: "DATE(timestamp)",
    updatePartitionFilter:
        "timestamp >= timestamp_sub(current_timestamp(), interval 24 hour)"
  }
}

SELECT timestamp, action FROM weblogs.user_actions
${ when(incremental(), `WHERE timestamp > (SELECT MAX(timestamp) FROM ${self()})`) }

パーティション分割テーブルから取り込む際に、完全なテーブル スキャンを回避する

パーティション分割テーブルを参照する増分テーブルを作成する場合、各増分更新でパーティション分割テーブルの完全なテーブル スキャンを回避するためにテーブルクエリを作成することをおすすめします。

テーブルクエリで定数式を使用して増分テーブルを更新するために、BigQuery がスキャンするパーティション数を制限できます。パーティション分割テーブルの値を定数式に変換するには、BigQuery スクリプトを使用して pre_operations ブロックで変数として値を宣言します。次に、SELECT クエリの WHERE 句で定数式として変数を使用します。

この構成により、Dataform はテーブル全体をスキャンすることなく、参照先パーティション分割テーブルの最新のパーティションに基づいて増分テーブルを更新します。

パーティション分割テーブルを参照し、完全なテーブル スキャンを回避する増分テーブルを構成するには、次の手順を行います。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. 増分テーブル定義の SQLX ファイルを選択します
  4. pre_operations ブロックで、BigQuery スクリプトを使用して変数を宣言します。
  5. 宣言された変数を参照する WHERE 句を使用して、テーブルを定義する SELECT ステートメントをフィルタします。
  6. 省略可: [書式] をクリックします。

次のサンプルコードは、参照先の raw_events テーブルが event_timestamp によって分割される増分テーブルを示しています。

config {
  type: "incremental",
}

pre_operations {
  DECLARE event_timestamp_checkpoint DEFAULT (
    ${when(incremental(),
    `SELECT max(event_timestamp) FROM ${self()}`,
    `SELECT timestamp("2000-01-01")`)}
  )
}

SELECT
  *
FROM
  ${ref("raw_events")}
WHERE event_timestamp > event_timestamp_checkpoint

上述のコードサンプルでは、event_timestamp_checkpoint 変数が pre_operations ブロックで定義されています。 event_timestamp_checkpoint 変数は、WHERE 句で定数式として使用されます。

フル更新で増分テーブルをゼロから再構築する

--full-refresh オプションを使用したコマンドライン インターフェース、またはワークフローの実行をトリガーするときに [フル更新で実行] を使用すると、増分テーブルをゼロから強制的に再構築できます。

フル更新オプションを選択した場合、開発ワークスペース、または Dataform CLI を使用して、Dataform は実行中に ${when(incremental(), ... } パラメータを無視し、CREATE OR REPLACE ステートメントでテーブルを再作成します。

フル更新から増分テーブルを保護する

増分テーブルをゼロから再作成して潜在的なデータ損失から保護するには、増分テーブルを protected として設定します。データソースが一時的なものである場合は、増分テーブルが再作成されないようにすることをおすすめします。

増分テーブルを protected としてマークする手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. 増分テーブル定義の SQLX ファイルを選択します。
  4. config ブロックに「protected: true」と入力します。
  5. 省略可: [書式] をクリックします。

次のコードサンプルは、protected とマークされた増分テーブルを示しています。

config {
  type: "incremental",
  protected: true
}
SELECT ...

フル更新なしで増分テーブル スキーマを変更する

onSchemaChange 構成プロパティを使用すると、テーブルを完全に更新することなく、SELECT クエリで増分テーブル スキーマを変更できます。このプロパティを使用すると、過去のデータを保持しながら、テーブルに新しい列を追加したり、既存の列を削除したりできます。このアプローチは、データ損失の防止に役立ち、BigQuery での手動更新を回避できます。

この機能を使用するには、Dataform コア 3.0.11 以降をインストールする必要があります。

onSchemaChange プロパティを設定すると、Dataform は SELECT クエリをチェックして、列が追加または削除されたかどうかを判断します。次に、Dataform は onSchemaChange プロパティの値で指定されたアクションを実行します。

onSchemaChange プロパティを設定する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. 増分テーブル定義の SQLX ファイルを選択します。
  4. この config ブロックに次のコード スニペットを入力します。

    onSchemaChange: "ON_CHANGE_ACTION"
    

    ON_CHANGE_ACTION は、次のいずれかのアクションに置き換えます。

    • IGNORE(デフォルト): 追加された列を無視し、欠落している列のエラーを表示します。onSchemaChange が設定されていない場合、スキーマが変更されると、これがデフォルトの動作になります。
    • FAIL: Dataform がスキーマの変更を検出すると、アクションを停止します。これにより、スキーマの整合性を維持できます。
    • EXTEND: クエリから増分テーブルに新しい列を追加し、以前のレコードに NULL 値を追加します。クエリの元のスキーマから列が削除されているか、欠落している場合にエラーが表示されます。この設定を使用すると、実行時に増分テーブルに新しい列を追加できます。
    • SYNCHRONIZE: クエリから増分テーブルに新しい列を追加し、以前のレコードに NULL 値を追加します。元のスキーマに存在していたが、現在のクエリに存在しない列を削除します。

  5. 省略可: [書式] をクリックします。

次のコードサンプルは、onSchemaChange プロパティに EXTEND アクションが設定された増分テーブルを示しています。

config {
    type: "incremental",
    onSchemaChange: "EXTEND",
}
SELECT ...

テーブル ドキュメントを追加する

このセクションでは、テーブルとその列とレコードの説明を Dataform コア SQLX ファイルに追加する方法について説明します。

テーブル、列、レコードの説明は、Dataform のすべてのテーブルタイプ(テーブル、増分テーブル、ビュー)に追加できます。

次の内容を文書化する場合があります。

  • テーブルの目的。
  • テーブル内の列またはレコードの内容または役割。
  • テーブルとワークフローの他のアクションの関係(現在のテーブルに依存するテーブルやビューなど)。
  • テーブルに適用されるアサーション。
  • テーブルに適用される前オペレーションまたは後オペレーション。
  • テーブルのオーナー(テーブルを作成したユーザー)。この情報は、複数のチームメンバーがワークフローに取り組む場合に役立ちます。

Knowledge Catalog のメタデータを追加する

BigQuery の標準メタデータ(データセット、テーブル、ビューなど)は、Knowledge Catalog で自動的に使用できます。

テーブルとビューのカスタム メタデータを、.sqlx ファイルの構成ブロックで直接定義することもできます。アクションが正常に完了すると、Dataform は自動的に Knowledge Catalog へのメタデータ同期を開始します。この拡充プロセスにより、SQLX 構成で定義されたセマンティック メタデータで Knowledge Catalog が更新されます。

メタデータキーを使用して、Knowledge Catalog の情報を指定します。拡充プロセスでは、次のメタデータ構造がサポートされています。

  • 概要: エントリのドキュメントと概要テキスト。Dataform コア バージョン 3.0.37 以降が必要です。
  • 一般的なアスペクト: テーブル システムやタイプ情報などのセマンティックの詳細。Dataform Core バージョン 3.0.52 以降が必要です。

次の構成例は、Knowledge Catalog のテーブル構成に概要と一般的なメタデータ アスペクトを追加する方法を示しています。

config {
  type: "table",
  metadata: {
    overview: "This table provides standardized trip data.",
    extraProperties: {
        generic: {
              system: "BigQuery",
              type: "table"
        }
      }
  }
}

メタデータの更新ステータスを確認するには、Dataform ワークフローのワークスペース実行ログを検査する、または BigQuery パイプラインの過去の手動実行を表示するをご覧ください。

同期されたメタデータを確認するには、Knowledge Catalog でアセットを検索します。詳しくは、リソースを検索するをご覧ください。

テーブルの説明を追加する

SQLX ファイルのテーブルに説明を追加する手順は次のとおりです。

  1. Google Cloud コンソールで、[Dataform] ページに移動します。

    Dataform に移動

  2. リポジトリを選択します。

  3. 開発ワークスペースを選択します。

  4. [ファイル] ペインで、編集するテーブル定義 SQLX ファイルをクリックします。

  5. ファイルの config ブロックに、次の形式でテーブルの説明を入力します。

    description: "Description of the table",
    
  6. 省略可: [書式] をクリックします。

次のコードサンプルは、SQLX テーブル定義ファイルの config ブロックに追加されたテーブルの説明を示しています。

config {
  type: "table",
  description: "Description of the table",
 }

列とレコードの説明を追加する

個々の列とレコードの説明を SQLX ファイルに追加する手順は次のとおりです。

  1. テーブル定義ファイルの config ブロックに「columns: {}」と入力します。
  2. columns: {} 内に、次の形式で列の説明を入力します。

    column_name: "Description of the column",
    
  3. columns: {} 内に、次の形式でレコードの説明を入力します。

      record_name: {
          description: "Description of the record",
          columns: {
            record_column_name: "Description of the record column"
          }
    }
    
  4. 省略可: [書式] をクリックします。

次のコードサンプルは、SQLX テーブル定義ファイルの config ブロック内のテーブル、列、レコードの説明を示しています。

config {
  type: "table",
  description: "Description of the table.",
  columns: {
    column1_name: "Description of the first column",
    column2_name: "Description of the second column",
    column3_name: "Description of the third column",
    record_name: {
      description: "Description of the record.",
      columns: {
       record_column1_name: "Description of the first record column",
       record_column2_name: "Description of the second record column",
      }
    }
  }
}
SELECT
  "first_column_value" AS column_1_name,
  "second_column_value" AS column_2_name,
  "third_column_value" AS column_3_name,
  STRUCT("first" AS record_column1_name,
    "second" AS record_column2_name) AS record_name

含まれる内容を使用して列のドキュメントを再利用する

JavaScript のインクルードを使用して、SQL ワークフロー全体で Dataform の列の説明を再利用できます。SQL ワークフローに同じ名前と説明を持つ複数の列がある場合は、列のドキュメントを再利用することをおすすめします。

1 つの列の説明を含む定数を定義することも、列の説明のセットを含む定数を定義して、テーブル内のすべての列の説明を再利用することもできます。Dataform でのインクルードの作成と使用の詳細については、インクルードを使用して単一のリポジトリ全体でコードを再利用するをご覧ください。

次のコードサンプルは、includes/docs.js JavaScript ファイルで定義された個々の列の説明を含む複数の定数を示しています。


// filename is includes/docs.js

const user_id = `A unique identifier for a user`;
const age = `The age of a user`;
const creation_date = `The date this user signed up`;
const user_tenure = `The number of years since the user's creation date`;
const badge_count = `The all-time number of badges the user has received`;
const questions_and_answer_count = `The all-time number of questions and answers the user has created`;
const question_count = `The all-time number of questions the user has created`;
const answer_count = `The all-time number of answers the user has created`;
const last_badge_received_at = `The time the user received their most recent badge`;
const last_posted_at = `The time the user last posted a question or answer`;
const last_question_posted_at = `The time the user last posted an answer`;
const last_answer_posted_at = `The time the user last posted a question`;

module.exports = {
   user_id,
   age,
   creation_date,
   user_tenure,
   badge_count,
   questions_and_answer_count,
   question_count,
   answer_count,
   last_badge_received_at,
   last_posted_at,
   last_question_posted_at,
   last_answer_posted_at,
};

次のコードサンプルは、includes/docs.js で定義された user_id 定数と age 定数を示しています。これは、テーブル内の選択した列のドキュメントを生成するために、definitions/my_table.sqlx SQLX テーブル定義ファイルで使用されます。

config {
  type: "table",
  description: "Table description.",
  columns: {
    user_id: docs.user_id,
    column2_name: "Description of the second column",
    column3_name: "Description of the third column",
    age: docs.age,
  }
}

SELECT ...

次のコードサンプルは、includes/docs.js JavaScript ファイルで定義された一連の列の説明を持つ定数です。


// filename is includes/docs.js

const columns = {
    user_id = `A unique identifier for a user`,
    age = `The age of a user`,
    creation_date = `The date this user signed up`,
    user_tenure = `The number of years since the user's creation date`,
    badge_count = `The all-time number of badges the user has received`,
    questions_and_answer_count = `The all-time number of questions and answers the user has created`,
    question_count = `The all-time number of questions the user has created`,
    answer_count = `The all-time number of answers the user has created`,
    last_badge_received_at = `The time the user received their most recent badge`,
    last_posted_at = `The time the user last posted a question or answer`,
    last_question_posted_at = `The time the user last posted an answer`,
    last_answer_posted_at = `The time the user last posted a question`,
}


module.exports = {
  columns
};

次のコードサンプルは、includes/table_docs.js で定義されている columns 定数を示しています。このテーブルは、definitions/my_table.sqlx SQLX テーブル定義ファイルでテーブル内のすべての列に関するドキュメントを生成するために使用されます。

config { type: "table",
description: "My table description",
columns: docs.columns
}

SELECT 1 AS one

BigQuery ラベルを追加する

このセクションでは、Dataform でテーブルにラベルを追加する方法について説明します。

BigQuery では、リソースにラベルを追加できます。BigQuery のラベルの詳細については、ラベルの概要をご覧ください。

Dataform のテーブルに BigQuery ラベルを追加するには、テーブル定義 SQLX ファイルの config ブロックの bigquery ブロックにラベルを追加します。

テーブル定義ファイルに BigQuery ラベルを追加する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を開きます。
  3. SQLX テーブル定義ファイルを選択します。
  4. config ブロックに、次の形式でラベルを追加します。

    bigquery: {
        labels: {
          LABEL1: "VALUE_OF_LABEL1"
        }
      }
    

    以下を置き換えます。

    • LABEL1: ラベルの名前
    • VALUE_OF_LABEL1: ラベルの値
  5. 省略可: 特殊文字を含む名前のラベルを追加するには、ラベル名を引用符("")で囲みます。

  6. 省略可: [書式] をクリックします。

次のコードサンプルは、パーティション分割テーブル定義 SQLX ファイルの bigquery ブロックに追加された department:shipping ラベルと cost-center:logistics ラベルを示しています。

config {
  type: "table",
  bigquery: {
    partitionBy: "DATE(ts)",
    labels: {
      department: "shipping",
      "cost-center": "logistics"
    }
  }
}

SELECT CURRENT_TIMESTAMP() AS ts

アクセス制御メタデータを保持する

Dataform がオブジェクトを再作成するワークフロー アクション(フル更新中の標準テーブル、ビュー、増分テーブルなど)を実行すると、通常、BigQuery で CREATE OR REPLACE ステートメントが生成され、オブジェクト スキーマとデータが更新されます。BigQuery のデフォルトでは、テーブル置換オペレーションにより、外部データ ガバナンス システムによって適用されたデータポリシーやデータ ガバナンス タグ(プレビュー)などの既存の列レベルのアクセス制御メタデータが自動的に削除されます。

preserveGovernanceControls オプションを有効にすると、ワークフローの実行全体で、既存の BigQuery データポリシー(タグなしデータポリシーを含む)とデータ ガバナンス タグを自動的に保持するように Dataform を構成できます。このオプションを有効にすると、Dataform は実行中に次のシーケンスを実行します。

  1. INFORMATION_SCHEMA.COLUMNS ビューから既存の列メタデータをバックアップします。
  2. 中間ステージング テーブル(空)を作成します。
  3. セキュリティ ポリシーを中間テーブルに再適用します。
  4. テーブルにデータを入力します。
  5. アトミック テーブル スワップを実行して、元のテーブルを置き換えます。

テーブルの自動ガバナンス保持を有効にする

個々のテーブル、増分テーブル、ビューのデータポリシーとデータ ガバナンス タグの自動保存を有効にするには、オブジェクトの SQLX 定義ファイルの config ブロックで preserveGovernanceControls パラメータを true に設定します。

個々のテーブルのガバナンス保持を構成する手順は次のとおりです。

  1. 開発ワークスペースに移動します。
  2. [ファイル] ペインで definitions/ を展開します。
  3. SQLX テーブル定義ファイルを選択します。
  4. config ブロックに「preserveGovernanceControls: true」と入力します。
  5. 省略可: [書式] をクリックします。

次のコードサンプルは、ガバナンスの保持が有効になっているテーブル定義を示しています。

config {
  type: "table",
  preserveGovernanceControls: true
}

SELECT
  customer_id,
  email,
  phone_number
FROM
  ${ref("raw_customers")}

すべてのテーブルに対して自動ガバナンス保持を有効にする

リポジトリの workflow_settings.yaml ファイルで preserveGovernanceControls パラメータを true に設定すると、リポジトリ内のすべてのテーブル、増分テーブル、ビューに対して、プロジェクト全体のデフォルトの動作として自動ガバナンス保持を有効にできます。

プロジェクト全体のデフォルトを設定するには、次の例に示すように、preserveGovernanceControls パラメータを workflow_settings.yaml ファイルに追加します。

defaultProject: my-gcp-project-id
defaultDataset: my_dataform_dataset
defaultLocation: US
defaultAssertionDataset: my_dataform_assertions
dataformCoreVersion: 3.0.62
preserveGovernanceControls: true

workflow_settings.yaml ファイルでガバナンス保持をグローバルに有効にしている場合は、この動作をオーバーライドして、特定のテーブルの保持を無効にできます。これを行うには、個々のテーブルの config ブロックで preserveGovernanceControls パラメータを false に設定します。

ポストオペレーションを使用して行アクセス ポリシーを再適用する

ガバナンスの保持を有効にすると、BigQuery データポリシーやデータ ガバナンス タグなどの列レベルのメタデータが自動的に保護されますが、行アクセス ポリシーは自動的に復元されません。オブジェクトの置換により既存の行レベルのセキュリティ ルールが削除されるため、SQLX テーブル定義ファイルの post_operations ブロック内で SQL DDL ステートメントを定義することで、テーブルの作成後に行アクセス ポリシーを再適用できます。

次のコードサンプルは、テーブルの post_operations ブロックで行アクセス ポリシーを再適用する方法を示しています。

config {
  type: "table",
}

SELECT
  bike_id,
  start_time,
  duration
FROM
  ${ref("raw_trips")}

post_operations {
  CREATE ROW ACCESS POLICY my_policy
  ON ${self()}
  GRANT TO ('serviceAccount:sa-name@example-gcp-project.')
  FILTER USING (bike_id LIKE 'US-%');
}

制限事項

ガバナンス保持機能を使用する場合は、次の制限事項を考慮してください。

  • スキーマ列の削除。SQLX テーブル定義から列が削除された場合、Dataform は、復元フェーズ中に削除された列に関連付けられているバックアップされたデータポリシーとタグを無視します。
  • スキーマ列の名前変更。SQLX テーブル定義で既存の列の名前を変更すると、Dataform は古いタグまたはポリシーの関連付けを新しい列名にマッピングできません。その結果、これらの列の既存のタグとポリシーが失われるか、入れ替わります。名前を変更した列にタグとポリシーを手動で再適用する必要があります。
  • パーティショニングとクラスタリングの変更。preserveGovernanceControls を使用する既存のテーブルのパーティショニングまたはクラスタリングの変更は、インプレースではサポートされていません。BigQuery は置換を拒否します。この問題を解決するには、テーブルを削除してワークフローを再度実行します。再作成されたテーブルに、列レベルのデータポリシーとデータ ガバナンス タグを手動で再適用する必要があります。
  • パーティションの有効期限の削除。構成から partitionExpirationDays プロパティを削除しても、既存のテーブルからパーティションの有効期限は削除されません。既存のテーブルからパーティションの有効期限を削除するには、オプションを選択した値に明示的に設定するか、テーブルを手動で変更する必要があります。
  • テーブルタイプ。正常に実行されると、テーブルはテーブル クローン(INFORMATION_SCHEMA.TABLES の table_type = 'CLONE')として報告されます。これは標準テーブルとして動作し、クローン メタデータに表示されるベーステーブルは存在しなくなります。
  • テーブルレベルのメタデータと行アクセス ポリシー。テーブルレベルのタグと行レベルのアクセス ポリシーは、実行間で保持されません。テーブルの作成後に、SQLX テーブル定義ファイルの post_operations ブロック内で SQL DDL ステートメントを定義することで、行アクセス ポリシーを再適用できます。
  • 非トランザクション テーブルのスワップ。BigQuery DDL オペレーションはトランザクションではありません。アトミックな名前変更シーケンスの途中でワークフローの実行が失敗した場合、ターゲット テーブルが中間状態のままになっていると、手動での介入が必要になることがあります。たとえば、テーブルの名前が TABLE_NAME_old に永続的に変更されている場合や、df_tmp_intermediate のままになっている場合です。
  • ポリシータグ。自動ガバナンス保持は、BigQuery ポリシータグをサポートしていません。代わりに、BigQuery データ ガバナンス タグ(プレビュー)とデータポリシーを列に追加して、組み込みの SQL 統合を使用します。

ストレージ費用に関する考慮事項

preserveGovernanceControls が有効になっている場合、Dataform は実行ごとに(増分テーブルの場合は完全更新ごとに)一時ステージング テーブルを介してテーブルを再構築します。BigQuery でのテーブルの再作成と同様に、以前のバージョンのテーブルデータは、データセットの構成済みウィンドウ(デフォルトでは 7 日間)のタイムトラベルに保持され、その後 7 日間のフェイルセーフ期間が続きます。

論理ストレージ課金は BigQuery のデフォルトの課金モデルですが、物理ストレージ課金はデータセットごとに構成されるオプトイン設定です。データセットで物理ストレージの課金を使用している場合、この保持されたタイムトラベル データとフェイルセーフ データは、アクティブ テーブルに加えて課金されます。その結果、頻繁に再構築される大きなテーブルでは、ストレージ費用が大幅に増加する可能性があります。

この費用を削減するには、次の操作を行います。

次のステップ