Google bigquery 数据流作业:无法将列分区表复制到列分区元表:不支持

Google bigquery 数据流作业:无法将列分区表复制到列分区元表:不支持,google-bigquery,Google Bigquery,我有一个Apache Beam项目,它使用Google Dataflow runner来处理BigQuery中存储的相当多的数据。该流读取1个主表,并使用3个不同的侧流。对于输入数据集中的每一行,我们计算一个“标签”,它生成5个不同的输出流。我们读取的主要BigQuery表是60GB,三个边流分别是2GB、51GB和110GB。这些都转换为PCollectionView 最后,这5个流被合并并写回BigQuery 当我在数据子集(100万行)上运行此作业时,该作业按预期工作,但当我在完整数据集(

我有一个Apache Beam项目,它使用Google Dataflow runner来处理BigQuery中存储的相当多的数据。该流读取1个主表,并使用3个不同的侧流。对于输入数据集中的每一行,我们计算一个“标签”,它生成5个不同的输出流。我们读取的主要BigQuery表是60GB,三个边流分别是2GB、51GB和110GB。这些都转换为
PCollectionView

最后,这5个流被合并并写回BigQuery

当我在数据子集(100万行)上运行此作业时,该作业按预期工作,但当我在完整数据集(1.77亿行)上运行此作业时,该作业返回以下错误:未能将列分区表复制到列分区元表:不支持

这个错误意味着什么?我怎样才能解决这个问题?谢谢

完整堆栈跟踪:

java.lang.RuntimeException: Failed to create copy job with id prefix beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00000, reached max retries: 3, last failed copy job: {
  "configuration" : {
    "copy" : {
      "createDisposition" : "CREATE_IF_NEEDED",
      "destinationTable" : {
        "datasetId" : "KPI",
        "projectId" : "bolcom-stg-kpi-logistics-f6c",
        "tableId" : "some_table_v1$20180811"
      },
      "sourceTables" : [ {
        "datasetId" : "KPI",
        "projectId" : "bolcom-stg-kpi-logistics-f6c",
        "tableId" : "beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00002_00000"
      }, {
        "datasetId" : "KPI",
        "projectId" : "bolcom-stg-kpi-logistics-f6c",
        "tableId" : "beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00001_00000"
      }, {
        "datasetId" : "KPI",
        "projectId" : "bolcom-stg-kpi-logistics-f6c",
        "tableId" : "beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00004_00000"
      }, {
        "datasetId" : "KPI",
        "projectId" : "bolcom-stg-kpi-logistics-f6c",
        "tableId" : "beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00003_00000"
      } ],
      "writeDisposition" : "WRITE_APPEND"
    }
  },
  "etag" : "\"HbYIGVDrlNbv2nDGLHCFlwJG0rI/oNgxlMGidSDy59VClvLIlEu08aU\"",
  "id" : "bolcom-stg-kpi-logistics-f6c:EU.beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00000-2",
  "jobReference" : {
    "jobId" : "beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00000-2",
    "location" : "EU",
    "projectId" : "bolcom-stg-kpi-logistics-f6c"
  },
  "kind" : "bigquery#job",
  "selfLink" : "https://www.googleapis.com/bigquery/v2/projects/bolcom-stg-kpi-logistics-f6c/jobs/beam_load_poisrschellenberger0810134033c63e44ed_e7cf725c5321409b96a4f20e7ec234bc_3d9288a5ff3a24b9eb8b1ec9c621e7dc_00000-2?location=EU",
  "statistics" : {
    "creationTime" : "1533957446953",
    "endTime" : "1533957447111",
    "startTime" : "1533957447111"
  },
  "status" : {
    "errorResult" : {
      "message" : "Failed to copy Column partitioned table to Column partitioned meta table: not supported.",
      "reason" : "invalid"
    },
    "errors" : [ {
      "message" : "Failed to copy Column partitioned table to Column partitioned meta table: not supported.",
      "reason" : "invalid"
    } ],
    "state" : "DONE"
  },
  "user_email" : "595758839781-compute@developer.gserviceaccount.com"
}.
    at org.apache.beam.sdk.io.gcp.bigquery.WriteRename.copy(WriteRename.java:166)
    at org.apache.beam.sdk.io.gcp.bigquery.WriteRename.writeRename(WriteRename.java:107)
    at org.apache.beam.sdk.io.gcp.bigquery.WriteRename.processElement(WriteRename.java:80)
要写入的表创建如下:

private static void write(final PCollection<TableRow> data) {
    // Write to BigQuery.
    data.apply(BigQueryIO.writeTableRows()
            .to(new GetPartitionFromTableRowFn("table_name"))
            .withSchema(getOutputSchema())
            .withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE_IF_NEEDED)
            .withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_APPEND));
}

private static TableSchema getOutputSchema() {
    final List<TableFieldSchema> fields = new ArrayList<>();
    fields.add(new TableFieldSchema().setName(ORDER_LINE_REFERENCE).setType("INTEGER"));
    fields.add(new TableFieldSchema().setName(COLUMN_LABEL).setType("STRING"));
    fields.add(new TableFieldSchema().setName(COLUMN_INSERTION_DATETIME).setType("TIMESTAMP"));
    fields.add(new TableFieldSchema().setName(COLUMN_PARTITION_DATE).setType("DATE"));
    return new TableSchema().setFields(fields);
}
私有静态无效写入(最终PCollection数据){
//写入BigQuery。
data.apply(BigQueryIO.writeTableRows()
.to(新的GetPartitionFromTableRowFn(“表格名称”))
.withSchema(getOutputSchema())
.withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE如果需要)
.withWriteDisposition(BigQueryIO.Write.WriteDisposition.Write_APPEND));
}
私有静态表模式getOutputSchema(){
最终列表字段=新的ArrayList();
add(new TableFieldSchema().setName(ORDER\u LINE\u REFERENCE).setType(“INTEGER”);
add(新的TableFieldSchema().setName(COLUMN_LABEL).setType(“STRING”);
add(new TableFieldSchema().setName(COLUMN_INSERTION_DATETIME).setType(“TIMESTAMP”);
fields.add(new TableFieldSchema().setName(COLUMN_PARTITION_DATE).setType(“DATE”);
返回新的TableSchema().setFields(fields);
}
使用以下序列化函数:

public class GetPartitionFromTableRowFn implements SerializableFunction<ValueInSingleWindow<TableRow>, TableDestination> {
    private final String tableDestination;

    public GetPartitionFromTableRowFn(final String tableDestination) {
        this.tableDestination = tableDestination;
    }

    public TableDestination apply(final ValueInSingleWindow<TableRow> element) {
        final TableDestination tableDestination;
        if (null != element.getValue()) {
            final TimePartitioning timePartitioning = new TimePartitioning().setType("DAY");
            timePartitioning.setField(Constants.COLUMN_PARTITION_DATE);
            final String formattedDate = element.getValue().get(Constants.COLUMN_PARTITION_DATE).toString().replaceAll("-", "");
            // e.g. output$20180801
            final String tableName = String.format("%s$%s", this.tableDestination, formattedDate);
            tableDestination = new TableDestination(tableName, null, timePartitioning);
        } else {
            tableDestination = new TableDestination(this.tableDestination, null);
        }

        return tableDestination;
    }
}
公共类GetPartitionFromTableRowFn实现SerializableFunction{
私人最终目的地;
public GetPartitionFromTableRowFn(最终字符串tableDestination){
this.tableDestination=tableDestination;
}
公共表目的地应用(最终值单窗口元素){
最终目的地表目的地;
if(null!=element.getValue()){
final TimePartitioning TimePartitioning=new TimePartitioning().setType(“DAY”);
timePartitioning.setField(Constants.COLUMN\u PARTITION\u DATE);
最终字符串formattedDate=element.getValue().get(Constants.COLUMN\u PARTITION\u DATE.toString().replaceAll(“-”,”);
//例如,产出201801美元
最终字符串tableName=String.format(“%s$%s”,this.tableDestination,formattedDate);
tableDestination=新的tableDestination(tableName,null,timePartitioning);
}否则{
tableDestination=新的tableDestination(this.tableDestination,null);
}
返回目的地;
}
}
1)您试图写入一个列分区表,该表在表后缀中被描述为分区装饰器:
某些表v1$20180811
这是不可能的。此语法仅适用于摄取时间分区的

由于表已根据错误消息按列进行分区,因此不支持此操作。您需要运行UPDATE或MERGE语句来更新基于列的分区,并且一个作业仅限于更改1000个分区。或者删除基于列的分区并仅使用摄取时间分区表

注意,BigQuery:

  • 基于摄入时间的
  • 基于列的
2) 如果不是这样,则需要再次检查源表:

复制多个分区表时,请注意以下事项:

  • 如果在同一作业中将多个源表复制到一个分区表中,则源表不能同时包含分区表和非分区表
  • 如果所有源表都是分区表,则所有源表的分区规范必须与目标表的分区规范匹配。您的设置决定是追加还是覆盖目标表。 源表和目标表必须位于同一位置的数据集中
注:有关更多详细信息,请发布您的表格定义

3) 查看此解决方案

1)您试图写入一个列分区表
,该表在表后缀中被描述为分区装饰器:
some_table\u v1$20180811
这是不可能的。此语法仅适用于摄取时间分区的

由于表已根据错误消息按列进行分区,因此不支持此操作。您需要运行UPDATE或MERGE语句来更新基于列的分区,并且一个作业仅限于更改1000个分区。或者删除基于列的分区并仅使用摄取时间分区表

注意,BigQuery:

  • 基于摄入时间的
  • 基于列的
2) 如果不是这样,则需要再次检查源表:

复制多个分区表时,请注意以下事项:

  • 如果在同一作业中将多个源表复制到一个分区表中,则源表不能同时包含分区表和非分区表
  • 如果所有源表都是分区表,则所有源表的分区规范必须与目标表的分区规范匹配。您的设置决定是追加还是覆盖目标表。 源表和目标表必须位于同一位置的数据集中
另外,如需了解更多详情,请将您的表格发布至