クエリ結果のページ分割

このドキュメントでは、BigQuery REST API を使用してクエリ結果のページ分割を行う方法について説明します。

API を使用した結果のページ分割

すべての collection.list メソッドから返される結果は、特定の状況下でページ分割されます。ページあたりの結果の数は maxResults プロパティによって制御されます。

メソッド ページ分割基準 maxResults のデフォルト値 maxResults の最大値
Tabledata.list レスポンス サイズがシリアル化された JSON で 10 MB を超える場合、または maxResults 行を超える場合は、ページ分割された結果を返します。 100,000 100,000
その他すべての collection.list メソッド レスポンスが maxResults 行を超える場合、ページ分割された結果を返します。 50 1,000

maxResults を上記の最大値より大きい値に設定すると、結果は最大値に基づいてページ分割されます。

ページは全行数のサブセットです。1 ページ分のデータを超える場合、結果データは pageToken プロパティを持ちます。次のページの結果を取得するには、別の list 呼び出しを行い、トークン値を pageToken という名前の URL パラメータとして指定します。

テーブルデータのページ分割に使用する bigquery.tabledata.list メソッドは行オフセット値またはページトークンを使用します。詳しくは、テーブルデータの閲覧をご覧ください。

BigQuery の結果をページ分割するサンプルを以下に示します。

C#

public int TableDataList(
    string datasetId, string tableId, int pageSize, BigQueryClient client)
{
    int recordCount = 0;
    var result = client.ListRows(datasetId, tableId, null,
        new ListRowsOptions { PageSize = pageSize });
    // If there are more rows than were returned in the first page of results,
    // iterating over the rows will lazily evaluate the results each time,
    // making further requests as necessary.
    foreach (var row in result)
    {
        Console.WriteLine($"{row["title"]}: {row["unique_words"]}");
        recordCount++;
    }
    return recordCount;
}

Java

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

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

Node.js 用の Google Cloud クライアント ライブラリでは、デフォルトで自動的に結果がページ分割されるため、ページ分割のためのコードを記述する必要はありません。次に例を示します。

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

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

// Creates a client
const bigquery = new BigQuery({
  projectId: projectId,
});

// Lists rows in the table
bigquery
  .dataset(datasetId)
  .table(tableId)
  .getRows()
  .then(results => {
    const rows = results[0];
    console.log('Rows:');
    rows.forEach(row => console.log(row));
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

PHP

PHP 用の Google Cloud クライアント ライブラリの場合、ジェネレータ関数 rows を使用すると、ページ分割が自動的に行われます。この関数は反復処理中に使用して、結果の次のページをフェッチします。

use Google\Cloud\BigQuery\BigQueryClient;

/**
 * Browse a bigquery table.
 * Example:
 * ```
 * browse_table($projectId, $datasetId, $tableId);
 * ```
 *
 * @param string $projectId  The Google project ID.
 * @param string $datasetId  The BigQuery dataset ID.
 * @param string $tableId    The BigQuery table ID.
 * @param string $maxResults The number of results to return at a time.
 * @param string $startIndex The row index to start on.
 *
 * @return int number of rows returned
 */
function browse_table($projectId, $datasetId, $tableId, $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++;
    }

    return $numRows;
}

Python

# 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

Ruby 用 Google Cloud クライアント ライブラリの場合、Table#dataData#next を使用すると、ページ分割が自動的に行われます。

# project_id = "Your Google Cloud project ID"
# dataset_id = "ID of the dataset containing table"
# table_id   = "ID of the table to display data for"

require "google/cloud/bigquery"

bigquery = Google::Cloud::Bigquery.new project: project_id
dataset  = bigquery.dataset dataset_id
table    = dataset.table table_id

table.data.each do |row|
  row.each      do |column_name, value|
    puts "#{column_name} = #{value}"
  end
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 "変更されていません" 結果を返し、値を返しません。この例として、ユーザーが BigQuery に格納されている情報を定期的に入力するウェブページがあります。ETag と If-None-Match ヘッダーを使用することにより、データに変更がない場合に冗長なリスト呼び出しを避けることができます。

  • 値が変更されていない場合にのみリスト値を返す場合:

    リストの値が変更されていない場合にのみリスト値のページを返す場合は、HTTP の "if-match" ヘッダーを使用できます。BigQuery は、ETag 値を比較し、結果が変更されていない場合は結果のページを返します。ページが変更されている場合は、412 "前提条件失敗" を返します。

注: Etag は冗長なリスト呼び出しを避けるために有効な方法ですが、同じ方法を使用して、いずれかのオブジェクトが変更されたかどうかを確認できます。たとえば、特定のテーブルに対する get リクエストを実行し、ETag を使用して、テーブルが完全なレスポンスを返す前に変更されているかどうかを判断できます。


このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。