对查询结果进行分页

本文档介绍如何通过 BigQuery REST API 对查询结果进行分页。

通过 API 对结果进行分页

在某些情况下,所有 collection.list 方法都会返回经分页的结果。每页的结果数由 maxResults 属性控制。

方法 分页标准 默认的 maxResults 最大 maxResults
Tabledata.list 如果响应大小超过 10 MB(序列化 JSON 文件)或多于 maxResults 行,则返回分页结果。 100000 100000
所有其他 collection.list 方法 如果响应多于 maxResults 行,则返回分页结果。 50 1000

如果设置的 maxResults 值大于上面列出的最大值,则会根据最大值对结果进行分页。

一个页面是总行数的子集。如果结果包含多页数据,则结果数据将具有 pageToken 属性。要检索下一页结果,请再次调用 list,并添加标记值作为名为“pageToken”的网址参数。

用于对表数据进行分页的 bigquery.tabledata.list 方法使用行偏移值或页面标记。详情请参阅浏览表数据

以下示例演示如何对 bigquery 结果进行分页。

C#

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 C# 设置说明进行操作。如需了解详情,请参阅 BigQuery C# API 参考文档

using Google.Api.Gax;
using Google.Apis.Bigquery.v2.Data;
using Google.Cloud.BigQuery.V2;
using System;
using System.Collections.Generic;
using System.Linq;

public class BigQueryBrowseTable
{
    public void BrowseTable(
        string projectId = "your-project-id"
    )
    {
        BigQueryClient client = BigQueryClient.Create(projectId);
        TableReference tableReference = new TableReference()
        {
            TableId = "shakespeare",
            DatasetId = "samples",
            ProjectId = "bigquery-public-data"
        };
        // Load all rows from a table
        PagedEnumerable<TableDataList, BigQueryRow> result = client.ListRows(
            tableReference: tableReference,
            schema: null
        );
        // Print the first 10 rows
        foreach (BigQueryRow row in result.Take(10))
        {
            Console.WriteLine($"{row["corpus"]}: {row["word_count"]}");
        }
    }
}

Java

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。如需了解详情,请参阅 BigQuery Java API 参考文档

TableId tableIdObject = TableId.of(datasetName, tableName);
// This example reads the result 100 rows per RPC call. If there's no need to limit the number,
// simply omit the option.
TableResult tableData =
    bigquery.listTableData(tableIdObject, TableDataListOption.pageSize(100));
for (FieldValueList row : tableData.iterateAll()) {
  // do something with the row
}

Go

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。如需了解详情,请参阅 BigQuery Go API 参考文档

默认情况下,Go 版 Google Cloud 客户端库会自动分页,因此您无需自行实现分页,例如:

table := client.Dataset(datasetID).Table(tableID)
it := table.Read(ctx)
for {
	var row []bigquery.Value
	err := it.Next(&row)
	if err == iterator.Done {
		break
	}
	if err != nil {
		return err
	}
	fmt.Println(row)
}

Node.js

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。如需了解详情,请参阅 BigQuery Node.js API 参考文档

默认情况下,Node.js 版 Google Cloud 客户端库会自动分页,因此您无需自行实现分页,例如:

// Import the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const datasetId = "my_dataset";
// const tableId = "my_table";

async function browseRows() {
  // Displays rows from "my_table" in "my_dataset".

  // Create a client
  const bigqueryClient = new BigQuery();

  // List rows in the table
  const [rows] = await bigqueryClient
    .dataset(datasetId)
    .table(tableId)
    .getRows();

  console.log('Rows:');
  rows.forEach(row => console.log(row));
}

browseRows();

PHP

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 PHP 设置说明进行操作。如需了解详情,请参阅 BigQuery PHP API 参考文档

生成器函数 rows 可在迭代期间获取下一页的结果,PHP 版 Google Cloud 客户端库使用此函数实现自动分页。

use Google\Cloud\BigQuery\BigQueryClient;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $datasetId = 'The BigQuery dataset ID';
// $tableId   = 'The BigQuery table ID';
// $maxResults = 10;

$maxResults = 10;
$startIndex = 0;

$options = [
    'maxResults' => $maxResults,
    'startIndex' => $startIndex
];
$bigQuery = new BigQueryClient([
    'projectId' => $projectId,
]);
$dataset = $bigQuery->dataset($datasetId);
$table = $dataset->table($tableId);
$numRows = 0;
foreach ($table->rows($options) as $row) {
    print('---');
    foreach ($row as $column => $value) {
        printf('%s: %s' . PHP_EOL, $column, $value);
    }
    $numRows++;
}

Python

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。如需了解详情,请参阅 BigQuery Python API 参考文档

默认情况下,Python 版 Google Cloud 客户端库会自动分页,因此您无需自行实现分页,例如:

# from google.cloud import bigquery
# client = bigquery.Client()

dataset_ref = client.dataset("samples", project="bigquery-public-data")
table_ref = dataset_ref.table("shakespeare")
table = client.get_table(table_ref)  # API call

# Load all rows from a table
rows = client.list_rows(table)
assert len(list(rows)) == table.num_rows

# Load the first 10 rows
rows = client.list_rows(table, max_results=10)
assert len(list(rows)) == 10

# Specify selected fields to limit the results to certain columns
fields = table.schema[:2]  # first two columns
rows = client.list_rows(table, selected_fields=fields, max_results=10)
assert len(rows.schema) == 2
assert len(list(rows)) == 10

# Use the start index to load an arbitrary portion of the table
rows = client.list_rows(table, start_index=10, max_results=10)

# Print row data in tabular format
format_string = "{!s:<16} " * len(rows.schema)
field_names = [field.name for field in rows.schema]
print(format_string.format(*field_names))  # prints column headers
for row in rows:
    print(format_string.format(*row))  # prints row data

Ruby

在尝试此示例之前,请先按照 BigQuery 快速入门:使用客户端库中的 Ruby 设置说明进行操作。如需了解详情,请参阅 BigQuery Ruby API 参考文档

Ruby 版 Google Cloud 客户端库使用 Table#dataData#next 自动分页。

require "google/cloud/bigquery"

def browse_table
  bigquery = Google::Cloud::Bigquery.new project_id: "bigquery-public-data"
  dataset  = bigquery.dataset "samples"
  table    = dataset.table "shakespeare"

  # Load all rows from a table
  rows = table.data

  # Load the first 10 rows
  rows = table.data max: 10

  # Print row data
  rows.each { |row| puts row }
end

请求任意页面并避免冗余列表调用

当使用缓存的 pageToken 值向后翻页或跳转到任意页面时,页面中的数据可能自上次查看后已更改,但没有数据可能已更改的明确指示。您可以使用 Etag 属性缓解此问题。

每个 collection.list 方法(Tabledata 除外)都会在结果中返回 Etag 属性。该属性是页面结果的哈希值,可用于验证自上次请求以来页面是否已更改。当使用 Etag 值向 BigQuery 发出请求时,BigQuery 会将 Etag 值与 API 返回的 ETag 值进行比较,并根据 ETag 值是否匹配做出响应。您可以使用 ETag 通过下列方式避免冗余列表调用:

  • 如果您只想在值已更改时返回列表值,请执行以下操作:

    如果您只想在值已更改时返回列表值,则可以通过 HTTP“if-none-match”标头使用先前存储的 ETag 进行列表调用。如果您提供的 ETag 与服务器上的 ETag 不匹配,BigQuery 将返回一页新列表值。如果 ETag 匹配,则 BigQuery 返回 HTTP 304“Not Modified”结果且没有值。例如,用户可能会定期在一个网页中填写信息,该信息存储在 BigQuery 中。通过使用 if-none-match 标头和 ETag,可以避免在未更改数据的情况下对 BigQuery 进行冗余列表调用。

  • 如果您只想在未更改值时返回列表值,请执行以下操作:

    如果您只想在未更改值时返回列表值页面,可以使用 HTTP“if-match”标头。如果结果未更改,则 BigQuery 会匹配 ETag 值并返回结果页面;如果该页面已更改,则返回 412“Precondition Failed”结果。

注意:尽管 ETag 是避免进行冗余列表调用的好方法,但您也可以将此方法用于识别任何对象是否已更改。例如,您可以针对特定表执行 Get 请求并使用 ETag,来确认该表在返回完整响应前是否更改。


此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面