我正试图使用BigQuery的Java客户端库对其表执行查询。我创建了一个Job,然后使用Job.getQueryResults((.iterateAll((方法获得Job的结果。
这种方式是可行的,但对于像600k这样的大数据,它需要大约80-120秒的时间。我看到BigQuery在40-45k个批次中获取数据,每个批次大约需要5-7秒。
我想更快地得到结果,我在互联网上发现,如果我们能从Job中获得BigQuery创建的临时表,并从该表中读取avro或其他格式的数据,那将非常快,但在BigQuery API(使用版本:1.124.7(中,我看不到这一点。有人知道如何在Java中做到这一点吗?或者在有大量记录的情况下如何更快地获取数据。感谢您的帮助。
读取表的代码(需要20秒(
Table table = bigQueryHelper.getBigQueryClient().getTable(TableId.of("project","dataset","table"));
String format = "CSV";
String gcsUrl = "gs://name/test.csv";
Job job = table.extract(format, gcsUrl);
// Wait for the job to complete
try {
Job completedJob = job.waitFor(RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
RetryOption.totalTimeout(Duration.ofMinutes(3)));
if (completedJob != null && completedJob.getStatus().getError() == null) {
log.info("job done");
// Job completed successfully
} else {
log.info("job has error");
// Handle error case
}
} catch (InterruptedException e) {
// Handle interrupted wait
}
使用查询读取同一表格的代码(需要90秒(
Job job = bigQueryHelper.getBigQueryClient().getJob(JobId.of(jobId));
for (FieldValueList row : job.getQueryResults().iterateAll()) {
System.out.println(row);
}
我尝试了某些方法,并在此基础上找到了最好的方法,只是想在这里发帖,以帮助未来的某个人。
1:如果我们在作业上或直接在表上使用job.getQueryResults((.iterateAll((,则需要相同的时间。因此,如果我们不给出批量大小,BigQuery将使用35-45k左右的批量大小来获取数据。因此,对于600k行(180Mb(,需要70-100秒。
2:我们可以使用创建作业中的临时表格详细信息,并使用表格的提取作业功能将结果写入GCS,这将更快,大约需要30-35秒。这种方法不会在本地下载,因此我们需要再次使用。。对临时表执行iterateAll((,它将花费与1相同的时间。
伪代码示例:
try {
Job job = getBigQueryClient().getJob(JobId.of(jobId));
long start = System.currentTimeMillis();
// FieldList list = getFields(job);
Job completedJob =
job.waitFor(
RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
RetryOption.totalTimeout(Duration.ofMinutes(3)));
if (completedJob != null && completedJob.getStatus().getError() == null) {
log.info("job done");
String gcsUrl = "gs://bucketname/test";
//getting the temp table information of the Job
TableId destinationTableInfo =
((QueryJobConfiguration) job.getConfiguration()).getDestinationTable();
log.info("Total time taken in getting schema ::{}", (System.currentTimeMillis() - start));
Table table = bigQueryHelper.getBigQueryClient().getTable(destinationTableInfo);
//Using extract job to write the data in GCS
Job newJob1 =
table.extract(
CsvOptions.newBuilder().setFieldDelimiter("t").build().toString(), gcsUrl);
System.out.println("DestinationInfo::" + destinationTableInfo);
Job completedJob1 =
newJob1.waitFor(
RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
RetryOption.totalTimeout(Duration.ofMinutes(3)));
if (completedJob1 != null && completedJob1.getStatus().getError() == null) {
log.info("job done");
} else {
log.info("job has error");
}
} else {
log.info("job has error");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
3:这是我想要的最好的方式。它在本地文件中更快地下载/写入结果。它下载数据大约需要20秒。这是BigQuery提供的新方式,可以使用以下链接进行检查:
https://cloud.google.com/bigquery/docs/reference/storage#background
列表项
https://cloud.google.com/bigquery/docs/reference/storage/libraries#client-库安装java