【问题标题】:BigQuery Select data based on Start Index and Last IndexBigQuery 根据开始索引和最后索引选择数据
【发布时间】:2022-01-27 16:53:28
【问题描述】:

我正在使用以下代码从 BigQuery 获取数据。

public class BQTEST {
    public static void main(String... args) throws Exception {
        String datasetName = "mydataset";
        String tableName = "mytable";
        String projectId = "gcs";
        String query =
                "SELECT id, " +
                        "qtr, " +
                        "sales, " +
                        "year " +
                        "FROM `gcs.mydataset.mytable` " +
                        ;
        BigQuery bigquery = BigQueryOptions.newBuilder().setProjectId(projectId)
                .setCredentials(
                        ServiceAccountCredentials.fromStream(new
                                FileInputStream("20a3c78f8388.json"))
                )
                .build().getService();
        TableId tableId = TableId.of(projectId, datasetName, tableName);
        QueryJobConfiguration queryConfig = QueryJobConfiguration
                .newBuilder(query)
                .build();
        try {
            bigquery.query(queryConfig);

        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        TableResult results = bigquery.listTableData(
                tableId,
                BigQuery.TableDataListOption.pageSize(1),
                BigQuery.TableDataListOption.startIndex(5)
        );

        for (FieldValueList row : results.iterateAll()) {
            System.out.printf(
                    "ID: %s qtr: %s sales: %s year: %s\n", row.get(0).getValue(), row.get(1).getValue(), row.get(2).getValue(), row.get(3).getValue());
        }


    }
}

BigQuery.TableDataListOption.startIndex(5) -- 这将有助于从第 5 个索引读取数据,索引从 0 开始。

但我想分块读取数据,例如一个进程中的前 10 条记录,然后是另一个进程中的下 20 条记录,等等。

尝试在并行进程中从一个非常大的表中读取数据。这是一个截断/加载表。所以没有分区和日期范围来读取数据。

我找不到在任何 BigQuery 方法中赋予 LAST_INDEX 值的方法。

有人可以帮忙吗?

【问题讨论】:

    标签: java google-cloud-platform google-bigquery


    【解决方案1】:

    没有LAST_INDEX 方法可以用于分页,因为您可以检查documentation。

    关于您的要求:

    我想以块的形式读取数据,例如一个进程中的前 10 条记录,然后是另一个进程中的下 20 条记录,等等,

    使用python,您可以使用max_results 和start_index 等一些参数来执行它,但在java 中,唯一的方法是对您的查询进行分页,并为每个进程更改它。因此,对于每个并行进程,您将有不同的查询。

    因此,每个进程都必须:

    1. 按某个字段(或所有字段)排序,以保证每个查询都以相同的顺序返回数据
    2. 使用limit 和offset 进行分页:

    即:

    String query = "SELECT id, qtr, sales, year FROM `gcs.mydataset.mytable` " +
                   "ORDER BY id, qtr, sales, year " +
                   "LIMIT 10 " +
                   "OFFSET " + String.valueOf(process_number * 10)
    ;
    

    进程 0 将有 0-9 行(限制 10 偏移 0);
    进程 1 将有第 10-19 行(限制 10 偏移 10)

    【讨论】:

    • 感谢您的回复。是的。有效。但是 OFFSET 和 LIMIT 将是较大表的开销,尤其是重新计票总数超过十亿的表。有没有其他最好的方法可以实现这个分块过程?
    • Bigquery 应该能够使用偏移量和限制轻松处理数十亿行,这应该不是问题。在您的情况下,当您想使用 java 在本地处理这些行时,这将是您的瓶颈。我建议您直接在 bigquery 上处理数据并仅返回结果。或者,如果您想要一个并行进程和更复杂的任务,我建议您在集群中使用 spark。在您自己的托管 Java 代码中一一处理数十亿行可能不是最好的。
    • 嗨@ewertonvsilva,如果我不担心订购,订购是强制性的吗?你能建议吗?使用 order by 运行查询时出现 resourcesExceeded 问题。
    • 嗨!是的,有必要强制 Bigquery 始终以相同的顺序返回数据集以启用分页。如果不使用,查询会以不同的顺序返回数据,使用limit/offset没有任何意义。
    • 谢谢。以下问题与此无关。请告知我是否应该创建单独的票。我们如何最好地处理 rateLimitExceed 问题。更频繁地面对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-08
    • 2019-01-01
    • 2014-11-27
    • 2013-10-09
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多