Snowflake「Dynamic table refresh failed」の原因と解決方法

Snowflakeダイナミックテーブルで「Dynamic table refresh failed」エラーが発生した状態を示すSnowsight画面イメージ Snowflake
この記事をシェアする𝕏B!FacebookLINEPocket

はじめに:ダイナミックテーブルが急に更新されなくなった!

Snowflakeで便利なダイナミックテーブル (Dynamic Table) を使い始めたものの、ある日突然「Dynamic table refresh failed」というエラーに遭遇して焦った経験はありませんか?データが古いままで止まっていて、なぜか自動で更新されない…そんなとき、原因の探し方さえ知っていれば、意外とすんなり解決できます。

この記事では、ダイナミックテーブルのリフレッシュが失敗する代表的な原因と、SnowsightやSQLでの調査・修正手順を解説します。

Snowflakeのダイナミックテーブルで発生する「Dynamic table refresh failed」エラーをテーマにした記事のアイキャッチ図解で、自動リフレッシュの停止原因とSnowsightやSQLによる調査・修正手順のポイントを示すビジュアル

そもそもダイナミックテーブルって何?

ダイナミックテーブルとは、SQLクエリの結果を定期的に自動で更新してくれるテーブルのことです。通常のビューはアクセスのたびにクエリを実行しますが、ダイナミックテーブルは「TARGET_LAG」と呼ばれる目標遅延時間に合わせて、Snowflakeが裏側で自動的にリフレッシュしてくれます。

イメージとしては、「結果が冷蔵庫に保存されている作り置きビュー」のような存在です。クエリが速く、しかも最新のデータに自動で更新される、というのが大きな魅力です。

リフレッシュの仕組み

ダイナミックテーブルは、指定したウェアハウスを使い、上流テーブルの変更を取り込んで自分の中身を更新します。この「自動更新の処理」がリフレッシュです。そして、何らかの理由でリフレッシュが失敗するとエラーログが残り、データが古いまま止まってしまいます。

「Dynamic table refresh failed」エラーの主な原因

エラーメッセージはシンプルですが、原因はいくつかのパターンに分かれます。一つずつ見ていきましょう。

① 上流テーブルの構造変更 (スキーマ変更)

ダイナミックテーブルが参照している上流テーブルのカラムが削除されたり、型が変わったりすると、SELECT文が成立しなくなり失敗します。「昨日まで動いていたのに急に止まった」ケースの多くがこれです。

② 権限の不足

ダイナミックテーブルは特定のロールで動作しますが、そのロールが上流テーブルに対するSELECT権限を失っていたり、ウェアハウスへのUSAGE権限がなくなっていたりするとリフレッシュできません。関連する権限エラーは Insufficient privileges to operate on の原因と解決手順Object does not exist or not authorized エラーの正体 もあわせて参考になります。

③ ウェアハウスがサスペンドや存在しない

リフレッシュに使うウェアハウスが削除されたり、リソースモニターでサスペンドされたりするとエラーになります。

④ クエリのタイムアウト・メモリ不足

上流データが急増してリフレッシュが重くなり、STATEMENT_TIMEOUT_IN_SECONDSを超えるとリフレッシュが失敗します。また、メモリ不足の場合は Memory limit exceeded エラー として現れることもあります。タイムアウト関連は Statement reached its statement timeout エラー も合わせてどうぞ。

⑤ データの不整合 (NULLや重複)

クエリ内にNOT NULL制約違反重複によるユニーク制約違反が混じると失敗します。特にMERGEやJOINを含むクエリでよく見られます。

エラー原因を調べる:DYNAMIC_TABLE_REFRESH_HISTORY

原因特定の第一歩は、Snowflakeが用意しているリフレッシュ履歴ビューを確認することです。

SELECT name,
       state,
       refresh_action,
       refresh_trigger,
       refresh_start_time,
       refresh_end_time,
       statistics:numInsertedRows AS inserted,
       error_code,
       error_message
FROM TABLE(
  INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(
    NAME => 'MY_DB.MY_SCHEMA.MY_DYNAMIC_TABLE'
  )
)
ORDER BY refresh_start_time DESC
LIMIT 20;

state列が「FAILED」になっている行のerror_messageに具体的な原因が出ています。ここを見れば「カラムが見つからない」「権限不足」など、本当の原因がわかります。

SnowflakeのINFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORYを実行し、state列がFAILEDの行とerror_messageにカラム不在や権限不足といった失敗原因が表示されたクエリ結果画面のスクリーンショット

具体的な解決手順

1. スキーマ変更が原因の場合

上流テーブルに合わせてダイナミックテーブルを再作成します。CREATE OR REPLACE DYNAMIC TABLEでクエリ部分を修正しましょう。

CREATE OR REPLACE DYNAMIC TABLE sales_summary
  TARGET_LAG = '5 minutes'
  WAREHOUSE = etl_wh
AS
SELECT customer_id, SUM(amount) AS total
FROM sales
GROUP BY customer_id;

2. 権限不足の場合

ダイナミックテーブルを所有するロールに、必要な権限を付与し直します。

GRANT USAGE ON WAREHOUSE etl_wh TO ROLE dt_owner_role;
GRANT SELECT ON TABLE sales TO ROLE dt_owner_role;

3. リフレッシュを手動で再開

原因を取り除いたら、ALTER DYNAMIC TABLE … REFRESHで手動再実行できます。

ALTER DYNAMIC TABLE sales_summary REFRESH;

また、サスペンド状態になっている場合は次のコマンドで再開しましょう。

ALTER DYNAMIC TABLE sales_summary RESUME;

4. TARGET_LAGの見直し

更新が頻繁すぎてリソースを食い潰している場合は、TARGET_LAGを少し緩めるのも有効です。

ALTER DYNAMIC TABLE sales_summary SET TARGET_LAG = '30 minutes';

よくあるユースケースと予防策

  • 監視を仕組み化する:DYNAMIC_TABLE_REFRESH_HISTORYを定期的にチェックするアラートを組むと、データ鮮度の低下にすぐ気づけます。
  • 上流テーブルの変更を周知:スキーマ変更は事前にチームで共有しましょう。
  • COPY INTOでロード失敗も連鎖する:上流の取り込み自体が失敗していると下流も止まります。COPY INTOが失敗する原因と解決方法も役立ちます。

まとめ

「Dynamic table refresh failed」エラーは、スキーマ変更・権限不足・タイムアウト・データ不整合のいずれかが原因であることがほとんどです。まずはDYNAMIC_TABLE_REFRESH_HISTORYでerror_messageを確認し、原因に応じた対処を行いましょう。修正後はALTER DYNAMIC TABLE ... REFRESHで手動再開すれば、データは無事に最新化されます。

ダイナミックテーブルはとても便利な機能ですが、「失敗時の調べ方」を知っているかどうかで運用の安定度がぐっと変わります。ぜひ今回の手順を引き出しにしまっておいてください。

参考リンク

関連記事

この記事をシェアする𝕏B!FacebookLINEPocket