dbt

dbt table マテリアライゼーション徹底ガイド: 再構築と性能特性を実務設計に落とし込む

2026-04-19
NicheeLab編集部

dbt の table マテリアライゼーションは、毎回フルにテーブルを作り直すシンプルさが強みです。一方で、データ量や基盤ごとの置換方式によってコストやロック挙動が変わるため、正しく理解して設計する必要があります。

この記事では、Analytics Engineer 受験者が押さえるべき公式挙動に基づき、再構築パターンと性能特性、選定基準、運用のコツを体系的に解説します。

table マテリアライゼーションの基本: 何が毎回起きているのか

table は、モデルを実行するたびにテーブル全体を再作成します。多くのアダプタでは CREATE OR REPLACE TABLE もしくは一時テーブルを作ってからアトミックにリネームする方式で、既存テーブルを丸ごと置き換えます。これにより、下流からは一貫したスナップショットとして参照されます。

インクリメンタルではないため、差分更新は行いません。スキーマ変更は再作成時に反映され、依存関係の解決は dbt の依存グラフに従います。ドキュメントの付与や権限付与は、アダプタがサポートしていれば post-hook や grants、persist_docs 設定で適用されます。

  • 再構築が前提: すべての行を再生成する
  • 置換はアダプタ依存: CREATE OR REPLACE もしくは tmp 作成→リネーム
  • 下流は一貫ビューを得やすいが、大規模テーブルではコスト増
  • スキーマ変更は毎回の再作成で自然に同期されやすい
マテリアライゼーション更新方式主な用途
table毎回フル再作成安定したスナップショット、集約・中間成果物
viewクエリ都度評価軽量な論理レイヤ、検証・小規模参照
incremental差分のみ挿入/マージ大規模データ、低コスト反復更新
ephemeral実体を持たない (CTE 展開)小さな前処理・再利用ロジック

table ビルドの高レベル流れ

sourcesstaging views[table model SQL]tmp_モデル名CTAS本番テーブルrename/swap 後に下流が参照

基本的な table モデルの設定例 (models/orders_rollup.sql)

{{ config(
    materialized = 'table',
    tags = ['daily'],
    persist_docs = {'relation': true, 'columns': true}
) }}

with base as (
  select * from {{ ref('stg_orders') }}
)
select customer_id,
       date_trunc(day, order_ts) as order_date,
       count(*) as order_cnt,
       sum(amount) as order_amount
from base
group by 1,2

再構築セマンティクスとアダプタ別の置換方式

table は通常実行時も “フルリフレッシュ” 相当の挙動です。つまり --full-refresh フラグの有無で処理が変わるのは主に incremental であり、table では常に再作成されます。

置換の安全性はアダプタにより異なります。CREATE OR REPLACE がある場合は単一文で置換可能、未対応の場合は tmp 作成→リネームや drop→create をトランザクション内で行います。これにより、失敗時には旧テーブルが残る・tmp が残置されるなどのパターンが発生し得ます。

  • table は毎回フルビルド。on_schema_change は incremental 向けで、table には通常関与しない
  • Snowflake/BigQuery/Databricks(Delta) は CREATE OR REPLACE を利用可能なことが多い
  • Redshift/Postgres 系は tmp→rename または drop→create の戦略が一般的
  • 失敗時の残置物 (tmp) のクリーンアップは運用上の点検ポイント
アダプタ例置換パターン原子的/トランザクション性の考慮
BigQueryCREATE OR REPLACE TABLE AS SELECT単一文置換。権限・メタ更新は文後に適用
SnowflakeCREATE OR REPLACE / 一時表→RENAMEリネームは原子的。失敗時は旧表が残ることが多い
Redshift/Postgrestmp 作成→RENAME または DROP→CREATEトランザクション内で整合性を担保
Databricks (Delta)CREATE OR REPLACE TABLE AS SELECTメタ更新は高速。最適化は別途 OPTIMIZE/VACUUM

tmp→rename 戦略の簡易シーケンス

StartCREATE TABLE tmp AS SELECT ...ALTER TABLE tmp RENAME TO targetsuccessCommitfailure 時は tmp 残置 → 運用で清掃

コンパイル後に近いイメージ (アダプタにより差異あり)

-- 例: CREATE OR REPLACE をサポートする場合
create or replace table analytics.orders_rollup as
select ...;
-- 例: tmp→rename を使う場合
create table analytics.orders_rollup__dbt_tmp as select ...;
alter table analytics.orders_rollup__dbt_tmp rename to analytics.orders_rollup;

性能特性とコスト: 何が効いて、何が効かないか

table は全件再作成のため、入力テーブルのスキャン量と集約処理がコスト・時間の主因になります。最適化の基本は、上流での前集約・不要列の削減・フィルタの早期適用です。物理設計としては、アダプタがサポートする partition/cluster/distribution の設定が、読み取りや書き込みのパスに影響します。

ただし、table である以上、モデル SQL が完全な結果セットを返す必要があります。単純に WHERE で最近分だけ読む設計は、結果が完全であるという要件を満たすときにのみ採用可能です(例えば上流がスナップショット累積を保持している場合など)。

  • 列削減・前集約・早期フィルタでスキャンコストを抑制
  • BigQuery: partition_by / cluster_by、Snowflake: CLUSTER BY、Databricks: ZORDER/OPTIMIZE などを適材適所で
  • 実行スケジュールはデータ到着とワークロードの隙間に置く
  • メトリクス監視: スキャンバイト数、シャッフル量、DML ステップ時間
レバー制御方法 (例)注意点
列・行の削減上流モデルで select 列最小化、早期 where結果の完全性を保つロジックであること
パーティション/クラスタconfig(partition_by=..., cluster_by=...)書き込み時のソート/シャッフル負荷に留意
計算リソースSnowflake: 仮想倉庫サイズ、BigQuery: スロット/定額短時間に集約してビルド時間を短縮
テーブル整理Databricks: OPTIMIZE/VACUUM, Snowflake: メンテメンテは実行ウィンドウ外で行う

性能ボトルネックの俯瞰

sourcestable modelscan/agg, partition/clustertargetwrite/replace → downstream readers

BigQuery でのパーティション・クラスタ設定例

{{ config(
    materialized = 'table',
    partition_by = { 'field': 'order_date', 'data_type': 'date' },
    cluster_by = ['customer_id']
) }}
select ... from {{ ref('stg_orders') }}

table を選ぶべきか: incremental との設計判断基準

table はシンプルで堅牢ですが、データ量が増えるとビルド時間と費用が増加します。日次〜時間単位での再計算が許容でき、全件再作成のコストが現実的な範囲に収まるなら有力です。逆に、到着データが多く、部分更新で十分に正を保てるなら incremental の方が有利です。

また、頻繁なスキーマ変更やロジックの試行錯誤が続くフェーズでは、table の再作成の方が変更伝搬が簡単です。安定期には、ホットパスだけ incremental に寄せるハイブリッドも現実解です。

  • 対象が中規模・再計算コストが見合うなら table
  • 遅延許容が低くデータ量が多いなら incremental 検討
  • スキーマ変更が多い期間は table が取り回しやすい
  • SLA とコストのバランスで段階的に移行する
条件table 向きincremental 向き
データ量/到着頻度小〜中、日次/時間単位大、準リアルタイム
スキーマ変化の頻度高い (毎回再作成で同期)低〜中 (差分管理が安定)
SLA/遅延要件分〜時間単位で許容短い遅延が必要
コスト最適化シンプル運用優先コンピュート節約優先

選定の判断フロー(簡易)

開始データ量は中規模以下?はい → table差分更新で正確性を保てる?はい → incrementalロジック再設計が多い?はい → 一時的に table / いいえ → 設計再検討

環境や変数で materialization を切替える例

{% set mat = var('mat_override', 'table') %}
{{ config(materialized = mat) }}
select ... from {{ ref('stg_orders') }}

-- 実行例: dbt run --vars "{mat_override: incremental}"

権限・ドキュメント・テスト適用: table 運用の基礎体力

table は物理リレーションとして存在するため、権限付与やコメント付与、カラム記述の永続化を設定で行えます。アダプタが grants と persist_docs をサポートしていれば、再作成後にも自動で適用されます。

制約・インデックスはアダプタ依存です。サポートされる場合は constraints や indexes 設定、あるいは post-hook で DDL を流します。スキーマテストは .yml で定義し、dbt build でモデルと一緒に検証します。

  • grants: 再作成後にも権限を維持するために必須
  • persist_docs: テーブル・カラムコメントを自動適用
  • 制約/インデックスはアダプタのサポート範囲を確認してから利用
  • dbt build でモデル作成とテストを一体運用
機能設定例補足
権限付与config(grants={'select': ['analyst_role']})アダプタが grants をサポートしている必要
ドキュメントpersist_docs={'relation': true, 'columns': true}コメント付与が可能な基盤で有効
制約/索引constraints / indexes / post-hook対応可否はアダプタ・バージョンに依存

dbt build による一体運用

model SQLbuild(table)apply grants/docstestsartifactsmanifest/run_results

モデルとスキーマテスト・権限の組合せ例

{{ config(
    materialized='table',
    grants={'select': ['ANALYST_ROLE']},
    persist_docs={'relation': true, 'columns': true}
) }}
select ...

# models/schema.yml
version: 2
models:
  - name: orders_rollup
    columns:
      - name: customer_id
        tests: [not_null]
      - name: order_date
        tests: [not_null]
      - name: order_amount
        tests: [not_null]

運用・障害時対応・並列度: 安定稼働のための実務ポイント

再作成はコンピュート負荷が高いため、他ジョブと重ならない時間帯にスケジュールし、ウェアハウスやスロットを適切に割り当てます。並列実行は依存関係が解決される範囲で有効ですが、同一スキーマでの大量同時置換はロック競合の原因になり得ます。

失敗時の残置物や半端な状態は、置換方式により異なります。tmp→rename 方式では、rename 前の失敗で旧テーブルが残り tmp が残置、rename 後の失敗で新テーブルは有効というケースが一般的です。CREATE OR REPLACE では置換自体が完了しなければ旧テーブルが残るのが通常です。

  • スケジュールは他ジョブと重ならないウィンドウに配置
  • コンピュートのスケールアップ/アウトで短時間集中実行
  • 失敗時の tmp 残置を監視・自動清掃
  • dbt build と選択子で影響範囲を最小化してリトライ
シナリオ期待される状態対応
tmp 作成後に失敗旧テーブルは存続、tmp が残置tmp のクリーンアップ自動化
rename 後に post-hook で失敗新テーブルは有効、hook 未適用hook のリトライ・冪等化
CREATE OR REPLACE 失敗旧テーブルが有効原因調査後に再実行

障害と残置物のタイムライン

t0: start buildt1: create tmp / begin replacet2: swap/renamet3: post-hooks (grants/docs)tX: failure?before t2 → 旧テーブル有効, tmp残置 / after t2 → 新テーブル有効

選択子・並列度の運用例

# 変更のあったモデルだけを対象
$ dbt build --select state:modified+

# 依存をまたいだ並列度(実行基盤に応じてジョブ並列)
$ dbt build --threads 8

問題で確認

Analytics Engineer

問題 1

dbt の table マテリアライゼーションに関する説明として最も適切なのはどれか。BigQuery を想定する。

  1. table は差分のみを書き込むため、--full-refresh を付けたときだけ全件再作成される
  2. table は毎回 view を更新するだけで物理テーブルは作らない
  3. table は通常実行でも全件再作成し、BigQuery では CREATE OR REPLACE TABLE を用いた置換が行われることが多い
  4. table では on_schema_change 設定が必須で、これがないと新規カラムは追加されない

正解: C

table は常にフル再作成であり、BigQuery では CREATE OR REPLACE TABLE による置換が一般的です。差分更新は incremental の挙動であり、on_schema_change は主に incremental 向けの設定です。

よくある質問

table でカラムを追加・削除した場合、どう反映されるか?

table は毎回テーブルを再作成するため、モデル SQL のスキーマがそのまま新しいテーブル定義になります。アダプタがコメント付与をサポートしていれば persist_docs で説明も更新されます。

大規模データで table を使う際のコスト対策は?

上流の前集約・列削減・早期フィルタを徹底し、パーティション/クラスタ設計を適用します。実行ウィンドウを分け、計算リソースを短時間スケールしてビルド時間を縮めるのも有効です。完全結果を返すロジックを維持しつつ、不要な再計算を避ける設計にします。

table と incremental の切り替えは安全にできるか?

可能です。移行時は一度 --full-refresh で完全再作成したうえで、incremental に切り替え、キーや on_schema_change、マージ条件を明確にします。逆に複雑化した incremental を一時的に table に戻して検証する運用もよく行われます。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.