Terraform使用google_bigquery_job插入BigQuery数据不修改表结构问询
问题原因
你使用WRITE_TRUNCATE写入模式时,BigQuery默认会用查询结果的Schema覆盖目标表的Schema:查询语句返回的字段默认是NULLABLE属性且无字段描述,因此会覆盖原表设置的REQUIRED约束和字段描述,导致Terraform下次执行时识别到表结构不一致,触发变更操作。
解决方案
方法1:修改google_bigquery_job配置,禁用Schema变更(推荐)
在query代码块中新增两个配置,显式禁止Job修改表结构:
allow_schema_relaxation = false:禁止放松Schema约束,避免REQUIRED字段被自动修改为NULLABLEschema_update_options = []:禁用所有Schema更新操作,避免字段描述、字段列表等被修改
修改后的google_bigquery_job配置示例:
resource "google_bigquery_job" "xyz" { job_id = "xyz_insert_${uuid()}" labels = merge(local.default_labels, { "workload2" : "test" }) project = var.project_id location = var.location query { query = "select 'test' as myfield" destination_table { project_id = google_bigquery_table.xyz.project dataset_id = google_bigquery_table.xyz.dataset_id table_id = google_bigquery_table.xyz.table_id } create_disposition = "CREATE_NEVER" write_disposition = "WRITE_TRUNCATE" # 新增配置开始 allow_schema_relaxation = false schema_update_options = [] use_legacy_sql = false # 新增配置结束 allow_large_results = true flatten_results = true script_options { key_result_statement = "LAST" } } }
配置生效后,如果查询返回的字段和目标表Schema不匹配,Job会直接执行失败,不会修改表结构,符合预期。
方法2:调整写入模式(业务允许前提下可选)
如果不需要全量覆盖历史数据,将write_disposition从WRITE_TRUNCATE改为WRITE_APPEND,该模式下默认不会修改原表Schema。
兜底方案(不推荐)
如果无法调整Job配置,可以在google_bigquery_table资源中添加生命周期规则,忽略Schema变更:
resource "google_bigquery_table" "xyz" { dataset_id = google_bigquery_dataset.xyz.dataset_id table_id = "xyz" description = "Contains some value" project = var.project_id labels = merge(local.default_labels, { "workload2" : "test" }) deletion_protection = var.deletion_protection schema = file("${path.module}/bigquery-schema/xyz.json") # 新增生命周期规则 lifecycle { ignore_changes = [schema] } }
该方案的缺点是后续你主动修改Schema文件时,Terraform不会识别到变更,需要手动处理表结构更新。
内容的提问来源于stack exchange,提问作者Bhavin
相关产品推荐
相关产品推荐

