👶

BigQuery Streaming Insert したデータは最大 90 分間 UPDATE/DELETE できない

に公開

はじめに

BigQuery の Python クライアント(google-cloud-bigquery)で Streaming Insert(insert_rows_json)を使って挿入したデータは、最大 90 分間 UPDATE/DELETE ができません。

この仕様と対処法を解説します(知っている方も多い気がしますが、備忘録です)。

BigQuery Python クライアントのデータ挿入方式

google-cloud-bigquery ライブラリには、大きく分けて 2 種類のデータ挿入方式があります:

方式 メソッド 特徴
Streaming Insert insert_rows(), insert_rows_json() 低レイテンシ
Load Job load_table_from_json(), load_table_from_file() など バッチ処理

Streaming Insert の制約

Streaming Insert で挿入されたデータは、一時的に「ストリーミングバッファ」に格納されます。

このバッファ内のデータには以下の制約があります:

  • ✅ SELECT は可能(データは見える)
  • ❌ UPDATE は不可能
  • ❌ DELETE も不可能

バッファからマネージドストレージにフラッシュされるまで、最大 90 分待つ必要があります。

対処法:Load Job を使う

Load Job はデータを直接マネージドストレージに書き込むため、ストリーミングバッファを経由しません。INSERT 直後に UPDATE/DELETE が可能です。

コード例

# Streaming Insert(INSERT 後に UPDATE/DELETE 不可)
def insert_rows(self, rows):
    errors = self.client.insert_rows_json(self.table_id, rows)
    if errors:
        raise RuntimeError(f"InsertRowsError: {errors}")

# Load Job(INSERT 後に UPDATE/DELETE 可能)
def insert_rows(self, rows):
    job_config = bigquery.LoadJobConfig(
        source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON,
        write_disposition=bigquery.WriteDisposition.WRITE_APPEND,
    )
    job = self.client.load_table_from_json(rows, self.table_id, job_config=job_config)
    job.result()

両方式の比較

項目 Streaming Insert Load Job
INSERT 後の DML 最大 90 分待機 即座に可能
レイテンシ 数秒 数秒〜十数秒
制限 なし 1,500 jobs/table/日
コスト $0.05/GB 無料

まとめ

  • Streaming Insert(insert_rows_json)で挿入したデータは最大 90 分間 UPDATE/DELETE できない
  • INSERT 後に DML 操作が必要な場合は Load Job(load_table_from_json)を使う

参考リンク

株式会社ZOZO

Discussion