Daten mit der BigQuery API und mit Paginierung lesen

In diesem Dokument wird beschrieben, wie Tabellendaten und Abfrageergebnisse mit der BigQuery API mithilfe von Paginierung gelesen werden.

Mit der API in Ergebnissen suchen

Bei allen Methoden vom Typ *collection*.list werden unter bestimmten Umständen Ergebnisse auf mehreren Seiten zurückgegeben. Das Attribut maxResults begrenzt die Anzahl der Ergebnisse pro Seite.

Methode Paginierungskriterien Standardwert für maxResults Höchstwert für maxResults Höchstwert für maxFieldValues
tabledata.list Gibt Ergebnisse mit Seitenumbrüchen zurück, wenn die Antwortgröße mehr als 10 MB1 an Daten oder mehr als maxResults Zeilen enthält. Unbegrenzt Unbegrenzt Unbegrenzt
Alle anderen *collection*.list-Methoden Gibt Ergebnisse mit Seitenumbrüchen zurück, wenn die Antwort mehr als maxResults Zeilen und außerdem die Höchstgrenze überschreitet. 10.000 Unbegrenzt 300.000

Wenn das Ergebnis größer als das Byte- oder Feldlimit ist, wird das Ergebnis gekürzt, um das Limit zu erreichen. Wenn eine Zeile das Byte- oder Feldlimit überschreitet, kann tabledata.list bis zu 100 MB Daten zurückgeben1. Dies entspricht der maximalen Zeilengröße für Abfragen. Es gibt keine Mindestgröße pro Seite. Einige Seiten geben möglicherweise mehr Zeilen als andere zurück.

1 Die Zeilengröße ist eine ungefähre Angabe, da die Größe auf der internen Darstellung der Zeilendaten basiert. Es kommt in bestimmten Phasen der Ausführung eines Abfragejobs zur Anwendung.

jobs.getQueryResults kann 20 MB Daten zurückgeben, sofern nicht explizit über den Support eine Anfrage angefordert wurde.

Eine Seite ist eine Teilmenge der Gesamtanzahl von Zeilen. Wenn die Ergebnisse mehr als eine Seite Daten umfassen, haben die Ergebnisdaten das Attribut pageToken. Mit einem weiteren list-Aufruf rufen Sie die nächste Seite mit Ergebnissen ab. Dabei nehmen Sie den Tokenwert als URL-Parameter mit dem Namen pageToken auf.

Die Methode tabledata.list zum Durchblättern von Tabellendaten verwendet einen Zeilenversatzwert oder einen Seitentoken. Weitere Informationen finden Sie unter In Tabellendaten suchen.

Ergebnisse der Clientbibliotheken iterieren

Die Cloud-Clientbibliotheken verarbeiten die Low-Level-Details der API-Paginierung und bieten eine Iterator-ähnliche Erfahrung, die die Interaktion mit den einzelnen Elementen in den Seitenantworten vereinfacht.

Die folgenden Beispiele zeigen das Durchblättern von BigQuery-Tabellendaten.

C#

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der C#-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery C# API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.


using Google.Api.Gax;
using Google.Apis.Bigquery.v2.Data;
using Google.Cloud.BigQuery.V2;
using System;
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

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Java-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Java API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQuery.TableDataListOption;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableResult;

// Sample to directly browse a table with optional paging
public class BrowseTable {

  public static void runBrowseTable() {
    // TODO(developer): Replace these variables before running the sample.
    String table = "MY_TABLE_NAME";
    String dataset = "MY_DATASET_NAME";
    browseTable(dataset, table);
  }

  public static void browseTable(String dataset, String table) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      // Identify the table itself
      TableId tableId = TableId.of(dataset, table);

      // Page over 100 records. If you don't need pagination, remove the pageSize parameter.
      TableResult result = bigquery.listTableData(tableId, TableDataListOption.pageSize(100));

      // Print the records
      result
          .iterateAll()
          .forEach(
              row -> {
                row.forEach(fieldValue -> System.out.print(fieldValue.toString() + ", "));
                System.out.println();
              });

      System.out.println("Query ran successfully");
    } catch (BigQueryException e) {
      System.out.println("Query failed to run \n" + e.toString());
    }
  }
}

Go

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Go-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Go API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

Die Google Cloud-Clientbibliothek für Go erstellt Seitenumbrüche standardmäßig automatisch. Deshalb müssen Sie die Seitenumbrüche nicht selbst einfügen. Beispiel:

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigquery"
	"google.golang.org/api/iterator"
)

// browseTable demonstrates reading data from a BigQuery table directly without the use of a query.
// For large tables, we also recommend the BigQuery Storage API.
func browseTable(w io.Writer, projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	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.Fprintln(w, row)
	}
	return nil
}

Node.js

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Node.js-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Node.js API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

Die Cloud-Clientbibliothek für Node.js erstellt Seitenumbrüche standardmäßig automatisch. Deshalb müssen Sie die Seitenumbrüche nicht selbst einfügen. Beispiel:

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

async function browseTable() {
  // Retrieve a table's rows using manual pagination.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = 'my_dataset'; // Existing dataset
  // const tableId = 'my_table'; // Table to create

  const query = `SELECT name, SUM(number) as total_people
    FROM \`bigquery-public-data.usa_names.usa_1910_2013\`
    GROUP BY name 
    ORDER BY total_people 
    DESC LIMIT 100`;

  // Create table reference.
  const dataset = bigquery.dataset(datasetId);
  const destinationTable = dataset.table(tableId);

  // For all options, see https://cloud.google.com/bigquery/docs/reference/rest/v2/Job#jobconfigurationquery
  const queryOptions = {
    query: query,
    destination: destinationTable,
  };

  // Run the query as a job
  const [job] = await bigquery.createQueryJob(queryOptions);

  // For all options, see https://cloud.google.com/bigquery/docs/reference/v2/jobs/getQueryResults
  const queryResultsOptions = {
    // Retrieve zero resulting rows.
    maxResults: 0,
  };

  // Wait for the job to finish.
  await job.getQueryResults(queryResultsOptions);

  function manualPaginationCallback(err, rows, nextQuery) {
    rows.forEach(row => {
      console.log(`name: ${row.name}, ${row.total_people} total people`);
    });

    if (nextQuery) {
      // More results exist.
      destinationTable.getRows(nextQuery, manualPaginationCallback);
    }
  }

  // For all options, see https://cloud.google.com/bigquery/docs/reference/v2/tabledata/list
  const getRowsOptions = {
    autoPaginate: false,
    maxResults: 20,
  };

  // Retrieve all rows.
  destinationTable.getRows(getRowsOptions, manualPaginationCallback);
}
browseTable();

PHP

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der PHP-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery PHP API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

Das Erstellen von Seitenumbrüchen erfolgt in den Cloud-Clientbibliotheken für PHP automatisch mit der Generatorfunktion rows. Diese ruft im Verlauf der Iteration die nächste Seite mit Ergebnissen ab.

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

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Python-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Python API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

Die Google Cloud-Clientbibliothek für Python erstellt Seitenumbrüche standardmäßig automatisch. Deshalb müssen Sie die Seitenumbrüche nicht selbst einfügen. Beispiel:


from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set table_id to the ID of the table to browse data rows.
# table_id = "your-project.your_dataset.your_table_name"

# Download all rows from a table.
rows_iter = client.list_rows(table_id)  # Make an API request.

# Iterate over rows to make the API requests to fetch row data.
rows = list(rows_iter)
print("Downloaded {} rows from table {}".format(len(rows), table_id))

# Download at most 10 rows.
rows_iter = client.list_rows(table_id, max_results=10)
rows = list(rows_iter)
print("Downloaded {} rows from table {}".format(len(rows), table_id))

# Specify selected fields to limit the results to certain columns.
table = client.get_table(table_id)  # Make an API request.
fields = table.schema[:2]  # First two columns.
rows_iter = client.list_rows(table_id, selected_fields=fields, max_results=10)
rows = list(rows_iter)
print("Selected {} columns from table {}.".format(len(rows_iter.schema), table_id))
print("Downloaded {} rows from table {}".format(len(rows), table_id))

# Print row data in tabular format.
rows = client.list_rows(table, max_results=10)
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

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Ruby-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Ruby API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

Das Erstellen von Seitenumbrüchen erfolgt in den Cloud-Clientbibliotheken für Ruby automatisch mit Table#data und Data#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

Beliebige Seiten anfordern und redundante Listenaufrufe vermeiden

Wenn Sie unter Verwendung von im Cache gespeicherten Werten für pageToken zurückblättern oder zu beliebigen Seiten springen, besteht die Möglichkeit, dass sich die Daten auf den Seiten seit der letzten Anzeige geändert haben. Es gibt jedoch keinen eindeutigen Hinweis darauf, dass sich die Daten möglicherweise geändert haben. Zur Umgehung dieses Problems verwenden Sie das Attribut etag.

Jede collection.list-Methode (mit Ausnahme von Tabledata) gibt das Attribut etag im Ergebnis zurück. Dieses Attribut ist ein Hash der Seitenergebnisse und kann verwendet werden, um zu prüfen, ob sich die Seite seit der letzten Anfrage geändert hat. Wenn Sie eine Anfrage in BigQuery mit einem ETag-Wert ausführen, vergleicht BigQuery den ETag-Wert mit dem ETag-Wert, der von der API zurückgegeben wird. Die Antwort fällt auf Basis der Übereinstimmung der ETag-Werte aus. Sie können ETags verwenden, um redundante Listenaufrufe zu vermeiden:

  • So erhalten Sie Listenwerte, wenn sich die Werte geändert haben.

    Möchten Sie eine Seite mit Listenwerten nur zurückgeben, wenn sich die Werte geändert haben, führen Sie einen Listenaufruf mit einem zuvor gespeicherten ETag durch. Dazu verwenden Sie den HTTP-Header "If-None-Match". Wenn der bereitgestellte ETag nicht mit dem ETag auf dem Server übereinstimmt, gibt BigQuery eine Seite mit neuen Listenwerten zurück. Wenn die ETags übereinstimmen, gibt BigQuery den Statuscode HTTP 304 Not Modified und keine Werte zurück. Ein Beispiel hierfür ist eine Webseite, auf der Nutzer regelmäßig Informationen eingeben, die in BigQuery gespeichert werden. Wenn keine Änderungen an Ihren Daten vorgenommen werden, können Sie redundante Listenaufrufe in BigQuery vermeiden, indem Sie den Header „if-none-match” mit ETags verwenden.

  • So erhalten Sie Listenwerte, wenn sich die Werte geändert haben.

    Möchten Sie eine Seite mit Listenwerten nur zurückgeben, wenn sich die Werte nicht geändert haben, verwenden Sie den HTTP-Header "If-Match". BigQuery vergleicht die ETag-Werte und gibt die Seite mit Ergebnissen zurück, wenn sich die Ergebnisse nicht geändert haben. Wenn sich die Seite geändert hat, gibt das Ergebnis 412 "Fehler bei Vorbedingung" zurück.

Hinweis: ETags eignen sich hervorragend zur Vermeidung von redundanten Listenaufrufen. Sie können aber auch die gleichen Methoden anwenden, um zu ermitteln, ob sich Objekte geändert haben. So können Sie beispielsweise eine GET-Anfrage für eine bestimmte Tabelle ausführen und ETags verwenden, um zu bestimmen, ob sich die Tabelle geändert hat, bevor die vollständige Antwort zurückgegeben wird.

In Abfrageergebnissen suchen

Bei jeder Abfrage wird in eine Zieltabelle geschrieben. Wenn keine Zieltabelle bereitgestellt wird, füllt die BigQuery API automatisch das Zieltabellenattribut mit einem Verweis auf eine temporäre anonyme Tabelle.

API

Lesen Sie das Feld jobs.config.query.destinationTable, um die Tabelle zu bestimmen, in die Abfrageergebnisse geschrieben wurden. Rufen Sie tabledata.list auf, um die Abfrageergebnisse zu lesen.

Java

Bevor Sie dieses Beispiel anwenden, folgen Sie den Schritten zur Einrichtung von Java in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Java API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableResult;

// Sample to run query with pagination.
public class QueryPagination {

  public static void main(String[] args) {
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String query =
        "SELECT name, SUM(number) as total_people"
            + " FROM `bigquery-public-data.usa_names.usa_1910_2013`"
            + " GROUP BY name"
            + " ORDER BY total_people DESC"
            + " LIMIT 100";
    queryPagination(datasetName, tableName, query);
  }

  public static void queryPagination(String datasetName, String tableName, String query) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      TableId tableId = TableId.of(datasetName, tableName);
      QueryJobConfiguration queryConfig =
          QueryJobConfiguration.newBuilder(query)
              // save results into a table.
              .setDestinationTable(tableId)
              .build();

      bigquery.query(queryConfig);

      TableResult results =
          bigquery.listTableData(tableId, BigQuery.TableDataListOption.pageSize(20));

      // First Page
      results
          .getValues()
          .forEach(row -> row.forEach(val -> System.out.printf("%s,\n", val.toString())));

      if (results.hasNextPage()) {
        // Next Page
        results
            .getNextPage()
            .getValues()
            .forEach(row -> row.forEach(val -> System.out.printf("%s,\n", val.toString())));
      }

      if (results.hasNextPage()) {
        // Remaining Pages
        results
            .getNextPage()
            .iterateAll()
            .forEach(row -> row.forEach(val -> System.out.printf("%s,\n", val.toString())));
      }

      System.out.println("Query pagination performed successfully.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Query not performed \n" + e.toString());
    }
  }
}

Verwenden Sie einen GetQueryResults-Job und legen Sie die Option pageSize des QueryResultsOption-Objekts, das Sie übergeben, wie im folgenden Beispiel gezeigt, fest, um die Anzahl der auf jeder Seite zurückgegebenen Zeilen festzulegen.

TableResult result = job.getQueryResults();
QueryResultsOption queryResultsOption = QueryResultsOption.pageSize(20);

TableResult result = job.getQueryResults(queryResultsOption);

Node.js

Bevor Sie dieses Beispiel anwenden, folgen Sie den Schritten zur Einrichtung von Node.js in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Node.js API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.

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

async function queryPagination() {
  // Run a query and get rows using automatic pagination.

  const query = `SELECT name, SUM(number) as total_people
  FROM \`bigquery-public-data.usa_names.usa_1910_2013\`
  GROUP BY name
  ORDER BY total_people DESC
  LIMIT 100`;

  // Run the query as a job.
  const [job] = await bigquery.createQueryJob(query);

  // Wait for job to complete and get rows.
  const [rows] = await job.getQueryResults();

  console.log('Query results:');
  rows.forEach(row => {
    console.log(`name: ${row.name}, ${row.total_people} total people`);
  });
}
queryPagination();

Python

Die Methode QueryJob.result gibt einen iterierbaren Wert der Abfrageergebnisse zurück. Sie haben folgende Alternativen:

  1. Lesen Sie das Attribut QueryJob.destination. Wenn dieses Attribut nicht konfiguriert ist, wird es von der API auf einen Verweis auf eine temporäre anonyme Tabelle festgelegt.
  2. Rufen Sie das Tabellenschema mit der Methode Client.get_table auf.
  3. Erstellen Sie mit der Methode Client.list_rows einen iterierbaren Wert für alle Zeilen in der Zieltabelle.

Bevor Sie dieses Beispiel ausprobieren, folgen Sie der Python-Einrichtungsanleitung in der BigQuery-Kurzanleitung zur Verwendung von Clientbibliotheken. Weitere Angaben finden Sie in der Referenzdokumentation zur BigQuery Python API.

Richten Sie zur Authentifizierung bei BigQuery die Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für Clientbibliotheken einrichten.


from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

query = """
    SELECT name, SUM(number) as total_people
    FROM `bigquery-public-data.usa_names.usa_1910_2013`
    GROUP BY name
    ORDER BY total_people DESC
"""
query_job = client.query(query)  # Make an API request.
query_job.result()  # Wait for the query to complete.

# Get the destination table for the query results.
#
# All queries write to a destination table. If a destination table is not
# specified, the BigQuery populates it with a reference to a temporary
# anonymous table after the query completes.
destination = query_job.destination

# Get the schema (and other properties) for the destination table.
#
# A schema is useful for converting from BigQuery types to Python types.
destination = client.get_table(destination)

# Download rows.
#
# The client library automatically handles pagination.
print("The query data:")
rows = client.list_rows(destination, max_results=20)
for row in rows:
    print("name={}, count={}".format(row["name"], row["total_people"]))