排查架构错误
本文档可帮助您诊断和解决在修改 BigQuery 表架构或定义或加载深度嵌套架构结构时发生的 HTTP 400 Bad Request 错误。如需了解如何使用 INFORMATION_SCHEMA 视图排查 BigQuery 性能问题,请参阅使用信息架构进行问题排查。
排查架构不匹配错误
当以下操作之一提供的架构与目标表的现有架构冲突时,BigQuery 会返回 Provided Schema does not match Table 错误 (reason: invalid):
- 加载作业
- 包含目标表的查询作业
- 复制作业
ALTER TABLEDDL 语句- 表元数据更新(
tables.update或tables.patch)
如需确定具体原因和出错提示,请将您的出错提示与以下场景之一进行匹配。
新架构中缺少字段
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Field FIELD_NAME is missing in new schema
诊断
以下操作之一提供的架构定义省略了目标表中已存在的一个或多个列:
- 加载作业
- DataFrame 写入操作
tables.update或tables.patchAPI 调用
解决方法
BigQuery 不允许通过从 API 架构载荷或加载作业配置中省略列来隐式删除列。如需解决此错误,请执行以下某项操作:
- 请更新您的流水线或 API 请求,使提供的架构包含目标表中的所有现有列。
如果您打算从表中移除该列,请运行
DROP COLUMNDDL 语句,而不是在加载或修补请求中省略该列:ALTER TABLE `PROJECT_ID.DATASET.TABLE` DROP COLUMN FIELD_NAME;替换以下内容:
PROJECT_ID:包含表的项目的 ID。DATASET:包含该表的数据集的名称。TABLE:表的名称。FIELD_NAME:要丢弃的列的名称。
字段类型已更改
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Field FIELD_NAME has changed type from EXISTING_TYPE to NEW_TYPE
诊断
您的请求尝试在加载作业或架构更新期间就地更改现有列的数据类型(例如,从 STRING 更改为 INT64)。
解决方法
如需解决此错误,请执行以下操作之一:
如果类型更改是受支持的列数据类型转换(例如
INT64到NUMERIC、INT64到FLOAT64或NUMERIC到BIGNUMERIC),请使用ALTER TABLE ... ALTER COLUMNDDL 语句:ALTER TABLE `PROJECT_ID.DATASET.TABLE` ALTER COLUMN FIELD_NAME SET DATA TYPE NEW_TYPE;替换以下内容:
PROJECT_ID:包含表的项目的 ID。DATASET:包含该表的数据集的名称。TABLE:表的名称。FIELD_NAME:要修改的列的名称。NEW_TYPE:目标数据类型。
如果不支持就地类型转换,请使用显式
CAST表达式查询现有数据,并将结果写入新表或覆盖现有表。如需了解详情,请参阅更改列的数据类型。
字段已更改模式
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Field FIELD_NAME has changed mode from EXISTING_MODE to NEW_MODE
诊断
您的请求尝试进行不受支持的列模式更改(例如,将 NULLABLE 更改为 REQUIRED,或将 REPEATED 更改为 NULLABLE)。如果您在 bq 命令行工具中使用内嵌架构定义来放宽包含 REPEATED 列的表上的 REQUIRED 列,也会发生此错误,因为 bq 命令行工具中的内嵌架构定义不支持修改包含 REPEATED 列的表。
解决方法
就地 BigQuery 架构更新支持的唯一模式更改是将列的模式从 REQUIRED 放宽到 NULLABLE。如需解决此错误,请执行以下某项操作:
- 如果您要将列从
REQUIRED放宽到NULLABLE,请在 GoogleSQL 中运行ALTER TABLE ... ALTER COLUMN ... DROP NOT NULLDDL 语句,或者如果您要使用bq update命令或tables.patchAPI 方法更新架构,请提供 JSON 架构文件。如需查看相关说明,请参阅更改列的模式。 - 如需将列的模式从
NULLABLE更改为REQUIRED,或从REPEATED更改为NULLABLE,请使用更新后的架构创建一个新表,然后将数据复制或加载到新表中。如需查看相关说明,请参阅修改表架构。
无法添加字段
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Cannot add fields (field: FIELD_NAME)
诊断
加载作业或查询作业包含目标表中不存在的列 (FIELD_NAME),并且作业配置中未启用架构添加。
解决方法
在加载或查询作业中启用架构添加:
- 在 REST API 或客户端库中,在加载或查询作业配置的
schemaUpdateOptions属性中添加ALLOW_FIELD_ADDITION。 - 在 bq 命令行工具中,传递
--schema_update_option=ALLOW_FIELD_ADDITION标志。 - 或者,在运行作业之前,使用
ALTER TABLE ... ADD COLUMN添加列。
无法向现有架构添加必填字段
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Cannot add required fields to an existing schema. (field: FIELD_NAME)
诊断
您的请求会将新列附加到现有表,并将列模式设置为 REQUIRED (NOT NULL)。由于表中的现有行会收到新添加列的 NULL 值,因此 BigQuery 会拒绝直接通过架构更新添加 REQUIRED 列。
解决方法
如需解决此错误,请执行以下操作之一:
- 添加模式为
NULLABLE而非REQUIRED的新列,然后运行 DMLUPDATE语句来填充现有行的值。 如需添加列并分配默认值,请完成以下步骤:
- 将该列添加为
NULLABLE列。 - 设置列的默认值,以便后续插入的数据自动获得一个值。
更新现有行以填充默认值:
ALTER TABLE `PROJECT_ID.DATASET.TABLE` ADD COLUMN FIELD_NAME DATA_TYPE; ALTER TABLE `PROJECT_ID.DATASET.TABLE` ALTER COLUMN FIELD_NAME SET DEFAULT DEFAULT_EXPRESSION; UPDATE `PROJECT_ID.DATASET.TABLE` SET FIELD_NAME = DEFAULT_EXPRESSION WHERE TRUE;替换以下内容:
PROJECT_ID:包含表的项目的 ID。DATASET:包含该表的数据集的名称。TABLE:表的名称。FIELD_NAME:新列的名称。DATA_TYPE:列的数据类型。DEFAULT_EXPRESSION:列的默认值表达式。
- 将该列添加为
架构中已存在该字段
错误消息
Field FIELD_NAME already exists in schema
诊断
API 请求、JSON 架构文件或源文件标头(例如 CSV 或 Parquet)中提供的架构包含重复的列名称。BigQuery 中的列名称不区分大小写,因此在同一架构中同时指定 Field_A 和 field_a 会触发此错误。
解决方法
检查源架构,并移除或重命名重复的列名称,包括任何不区分大小写的名称冲突。
不支持更新字段排序规则
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Invalid schema update. Updating field collation is not supported. Field FIELD_NAME has changed collation from "EXISTING_COLLATION" to "NEW_COLLATION"
诊断
在架构更新期间,您无法修改或移除现有列的排序规则规范。当应用提取表的架构、修改其他字段并使用不保留 collation 字段属性的旧版客户端库(发送 "" 而不是 "und:ci")将架构写回时,通常会发生此错误。
解决方法
要解决此错误,请执行以下操作:
- 将 BigQuery 客户端库升级到最新版本,以便在读取和修补表元数据时保留现有的
collation属性。 - 如果您手动构建 JSON 架构载荷,请确保现有列上的
collation属性与表的当前架构匹配。
缩小类型形参不兼容
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Narrowing type parameters is not compatible
诊断
您的 ALTER TABLE ... ALTER COLUMN ... SET DATA TYPE 语句尝试缩减参数化数据类型的最大长度、精度或标度,例如将 STRING(100) 更改为 STRING(50) 或缩减 NUMERIC(P, S) 参数。
解决方法
BigQuery 仅允许在现有列上就地放宽类型参数(例如,将 STRING(50) 增加到 STRING(100))。如需强制执行更窄的类型参数,请创建一个使用更窄类型参数定义的新表,并使用 SELECT 查询将数据复制或加载到新表中,使值符合更窄的类型(例如,STRING 列的 LEFT(FIELD_NAME, 50))。写入长度超过列最大长度的 STRING 或 BYTES 值,或者写入位数超过其精度允许的 NUMERIC 值,都会返回错误。小数位数多于列的小数位数的 NUMERIC 值会被四舍五入。如需了解详情,请参阅修改表架构。
不支持添加具有默认值的字段
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Add field with default value to an existing table schema is not supported; Field: FIELD_NAME. ...
诊断
您的加载作业或 tables.patch 或 tables.update API 请求尝试向现有表添加新列,同时在 API schema 载荷中指定 defaultValueExpression。您无法在单次 API 架构更新中向现有表添加具有默认值的新列。
解决方法
在 API 请求中添加列时,请先添加列,然后设置其默认值,而不是指定 defaultValueExpression(如需了解详情,请参阅限制):
如果您尚未添加该列,请运行以下语句,然后在不使用
defaultValueExpression的情况下恢复加载:ALTER TABLE `PROJECT_ID.DATASET.TABLE` ADD COLUMN FIELD_NAME DATA_TYPE; ALTER TABLE `PROJECT_ID.DATASET.TABLE` ALTER COLUMN FIELD_NAME SET DEFAULT DEFAULT_EXPRESSION; UPDATE `PROJECT_ID.DATASET.TABLE` SET FIELD_NAME = DEFAULT_EXPRESSION WHERE TRUE;替换以下内容:
PROJECT_ID:包含表的项目的 ID。DATASET:包含该表的数据集的名称。TABLE:表的名称。FIELD_NAME:新列的名称。DATA_TYPE:列的数据类型。DEFAULT_EXPRESSION:列的默认值表达式。
如果您已通过重新提交不含
defaultValueExpression的请求添加了该列,请仅运行上述示例中的ALTER COLUMN ... SET DEFAULT和UPDATE语句。
不支持更新现有标识列的属性
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Updating an existing identity column's attributes is not supported. Field FIELD_NAME already has identity column info.
诊断
您的请求尝试通过架构更新或 API 补丁修改现有标识列的属性。
解决方法
标识列属性在创建后无法就地修改。在架构更新载荷中保持现有标识列定义不变,或者使用更新后的标识列配置创建新表,然后将数据复制或加载到新表中。如需查看相关说明,请参阅修改表架构。
RECORD 列中不兼容的字段更改
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Incompatible field change within RECORD column
诊断
您的 ALTER TABLE ... ALTER COLUMN ... SET DATA TYPE 语句指定的 STRUCT 类型与列的现有类型不兼容。例如,新类型添加或移除子字段、将子字段更改为不受支持的类型,或缩小了子字段的类型参数。
解决方法
将 ALTER TABLE 语句中的 STRUCT 类型与列的现有架构进行比较,然后执行以下操作之一:
- 以相同顺序保留相同的子字段,并且仅以列数据类型更改支持的方式更改子字段类型。
- DDL 无法向现有
RECORD列添加嵌套子字段。而是应使用 JSON 架构文件通过bq update或tables.patch方法更新架构。如需了解详情,请参阅向RECORD列添加嵌套列。 - 如需移除或重构嵌套子字段,请参阅修改嵌套列类型。
已达到不同物理架构的数量上限
错误消息
Provided Schema does not match Table PROJECT_ID:DATASET.TABLE. Maximum limit on diverging physical schemas reached.
诊断
某些表架构修改(例如删除或重命名列)可能会导致表在 API 中具有相同的逻辑架构,但具有不同的底层物理架构表示形式。当您将数据复制到跨太多不同物理架构版本的目标表时,表复制作业可能会失败并出现此错误。如需了解详情,请参阅复制表的限制。
解决方法
使用 CREATE TABLE LIKE DDL 语句重新创建目标表,使其物理架构表示与源表的架构匹配,然后复制或插入数据:
CREATE OR REPLACE TABLE `PROJECT_ID.DATASET.DESTINATION_TABLE`
LIKE `PROJECT_ID.DATASET.SOURCE_TABLE`;
INSERT INTO `PROJECT_ID.DATASET.DESTINATION_TABLE`
SELECT * FROM `PROJECT_ID.DATASET.SOURCE_TABLE`;替换以下内容:
PROJECT_ID:包含表的项目的 ID。DATASET:包含这些表的数据集的名称。DESTINATION_TABLE:要重新创建的目标表的名称。SOURCE_TABLE:源表的名称。
排查架构、文件和例程嵌套限制错误
BigQuery 对 STRUCT (RECORD) 列、结构化加载文件以及嵌套例程参数和返回值类型强制执行 15 层的最大嵌套深度。如果超出此 15 级限制,系统会返回 HTTP 400 Bad
Request 错误,并显示以下消息之一(其中 MAX_DEPTH 和 MAX_LEVEL 为 15)。对于因超出逻辑视图或用户定义的永久性函数 (UDF) 的 16 级嵌套限制而导致的错误,请参阅嵌套视图或用户定义的永久性函数过多。
错误消息
Schema nested too deeply.Schema nested too deeply for field FIELD_NAME, maximum allowed depth is MAX_DEPTH.Field 'FIELD_NAME' is nested too deeply. It has definition level LEVEL while maximum allowed definition level is MAX_LEVEL.Schema nested too deeply, at least LEVEL compared to the maximum allowed level of 15.Routine TYPE_DESCRIPTION nested too deeply; max allowed depth: MAX_DEPTH
诊断
STRUCT (RECORD) 类型的列可以包含嵌套 RECORD 字段,最大深度为 15 级,无论这些字段是标量(NULLABLE 或 REQUIRED)还是基于数组 (REPEATED)。同样,JSON、Parquet 和 Avro 加载作业以及外部表在解析嵌套结构时也会强制执行嵌套限制。对于 Parquet 文件,该限制表示为最大定义级别和最大重复级别。
在例程错误中,TYPE_DESCRIPTION 标识嵌套类型:argument type、return type 或 return table type。
解决方法
此限制无法提高。如需解决此错误,请执行以下操作之一:
- 展平架构或例程类型定义。将表架构或例程参数和返回值类型中的深度嵌套
STRUCT或ARRAY层次结构拆分为单独的相关表,并在查询时联接它们,或将深度嵌套的属性提升为更高级别的列。 - 使用内置的
JSON数据类型。如果您的数据需要超过 15 层的嵌套,请将深度嵌套的子树存储在JSON(或STRING)类型的列中。JSON列在表架构中存储为单个列,从而避免了 15 层RECORD架构限制,同时仍允许您在查询时使用 JSON 字段访问运算符和函数来提取深度嵌套的路径。 - 在加载前预处理输入文件。如果错误发生在从 Cloud Storage 中的 JSON、Parquet 或 Avro 文件执行加载作业期间,请添加上游预处理步骤,以在将深度超过 15 层的结构加载到 BigQuery 之前将其展平或序列化。