从 Google Cloud BigQuery 读取数据

Posted

技术标签:

【中文标题】从 Google Cloud BigQuery 读取数据【英文标题】:Reading data from Google Cloud BigQuery 【发布时间】:2016-04-25 22:13:46 【问题描述】:

我是 Pipeline 世界和 Google API DataFlow 的新手。

我想用 sqlQuery 从 BigQuery 读取数据。当我读取所有数据库时,它工作正常。

PipelineOptions options = PipelineOptionsFactory.create();
Pipeline p = Pipeline.create(options);
PCollection<TableRow> qData = p.apply(
     BigQueryIO.Read
         .named("Read")
         .from("test:DataSetTest.data"));

但是当我使用 fromQuery 时出现错误。

PipelineOptions options = PipelineOptionsFactory.create();
Pipeline p = Pipeline.create(options);
PCollection<TableRow> qData = p.apply(
     BigQueryIO.Read
         .named("Read")
         .fromQuery("SELECT * FROM DataSetTest.data"));

错误:

线程“主”java.lang.IllegalArgumentException 中的异常: 查询“SELECT * FROM DataSetTest.data”的验证失败。如果 查询取决于管道的早期阶段,此验证可以 使用#withoutValidation 禁用。

在 com.google.cloud.dataflow.sdk.io.BigQueryIO$Read$Bound.dryRunQuery(BigQueryIO.java:449)

在 com.google.cloud.dataflow.sdk.io.BigQueryIO$Read$Bound.validate(BigQueryIO.java:432)

在 com.google.cloud.dataflow.sdk.Pipeline.applyInternal(Pipeline.java:357)

在 com.google.cloud.dataflow.sdk.Pipeline.applyTransform(Pipeline.java:267)

在 com.google.cloud.dataflow.sdk.values.PBegin.apply(PBegin.java:47)

在 com.google.cloud.dataflow.sdk.Pipeline.apply(Pipeline.java:151)

在 Test.java.packageid.StarterPipeline.main(StarterPipeline.java:72)

原因:java.lang.NullPointerException:必需参数 必须指定 projectId。

在 com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:229)

在 com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:140)

在 com.google.api.services.bigquery.Bigquery$Jobs$Query.(Bigquery.java:1751)

在 com.google.api.services.bigquery.Bigquery$Jobs.query(Bigquery.java:1724)

在 com.google.cloud.dataflow.sdk.io.BigQueryIO$Read$Bound.dryRunQuery(BigQueryIO.java:445)

...还有 6 个

这里有什么问题?

更新:

我通过“options.setProject”设置项目。

PipelineOptions options = PipelineOptionsFactory.create();
    Pipeline p = Pipeline.create(options);
    options.setProject("test");
    PCollection<TableRow> qData = p.apply(
         BigQueryIO.Read
             .named("Read")
             .fromQuery("SELECT * FROM DataSetTest.data"));

但现在我收到了这条消息。找不到表。

原因:com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found “代码”:404, “错误”:[ “域”:“全球”, “消息”:“未找到:表测试:_dataflow_temporary_dataset_737099.dataflow_temporary_table_550832”, “原因”:“未找到” ], “消息”:“未找到:表测试:_dataflow_temporary_dataset_737099.dataflow_temporary_table_550832”

【问题讨论】:

【参考方案1】:

Google Cloud Platform 中的所有资源(包括 BigQuery 表和 Dataflow 作业)都与一个云项目相关联。与 GCP 资源交互时需要指定项目。

异常跟踪表明没有为BigQueryIO.Read 转换设置云项目:Caused by: java.lang.NullPointerException: Required parameter projectId must be specified

Dataflow 通过其PipelineOptions API 控制云项目的默认值。 Dataflow 将默认跨其 API 使用该项目,包括 BigQueryIO

通常,我们建议使用PipelineOptionsFactory.fromArgs(String) API 从命令行参数构造PipelineOptions。在这种情况下,您只需在命令行中传递 --project=YOUR_PROJECT

或者,也可以在代码中手动设置,如下:

GcpOptions gcpOptions = options.as(GcpOptions.class);
options.setProject("YOUR_PROJECT");

最后,从 Dataflow SDK for Java 1.4.0 版本开始,Dataflow 将默认使用通过gcloud config set project &lt;project&gt; 设置的云项目。您仍然可以通过PipelineOptions 覆盖它,但不需要这样做。这可能在 1.4.0 版本之前的某些场景中有效,但在所有场景或 Cloud SDK 和 Dataflow SDK 版本的组合中可能并不可靠。

【讨论】:

我已经用 Google Cloud SDK 指定了项目。 不幸的是,Google Cloud SDK 更改了它填充项目 ID 的位置。因此,存在一种场景以及 Cloud SDK 和 Dataflow SDK 版本的组合,其中可能不会跨 SDK 自动填充。这应该在几天后发布的 Dataflow SDK 1.4.0 及更高版本中得到解决。同时,请注明--projectPipelineOption 我需要存储桶来访问来自 GC BigQuery 的数据吗? 听起来与原始问题无关。存储桶是 Google Cloud Storage (GCS) 使用的概念。要将作业提交到 Dataflow 服务,您必须指定“GCS 中的暂存位置”。因此,您需要有一个 GCS 存储桶来提交任何 Dataflow 作业。这与 BigQuery 完全正交——BigQuery 没有也不需要存储桶。

以上是关于从 Google Cloud BigQuery 读取数据的主要内容,如果未能解决你的问题,请参考以下文章