从 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 读取数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 google.cloud 导入 bigquery 模块

从 google.cloud 导入 bigquery ModuleNotFoundError:没有名为“google”的模块

从 Google Cloud BigQuery 读取数据

`TFRecord` 从 Google BigQuery 转储到 Google Cloud Storage

com.google.cloud.bigquery.BigQueryException:读取超时

从 Google Cloud Datastore 到 BigQuery 的增量数据传输