Paging dei dati delle tabelle

Questo documento descrive come sfogliare i dati delle tabelle e i risultati delle query utilizzando l'API REST di BigQuery.

Risultati di navigazione tramite l'API

Tutti i metodi *collection*.list restituiscono risultati impaginati in determinate circostanze. La proprietà maxResults limita il numero di risultati per pagina.

Metodo Criteri di impaginazione Valore maxResults predefinito Valore massimo maxResults Valore massimo maxFieldValues
tabledata.list Restituisce risultati impaginati se le dimensioni della risposta superano i 10 MB1 di dati o più di maxResults righe. Nessun limite Nessun limite Nessun limite
Tutti gli altri metodi (*collection*.list) Restituisce risultati impaginati se la risposta è superiore a maxResults righe e inferiore ai limiti massimi. 10.000 Nessun limite 300.000

Se il risultato è maggiore del limite di byte o di campo, il risultato viene tagliato per rientrare nel limite. Se una riga supera il limite di byte o campi, tabledata.list può restituire fino a 100 MB di dati1, coerentemente con il limite massimo di dimensioni delle righe per i risultati delle query.

1La dimensione della riga è approssimativa, poiché la dimensione si basa sulla rappresentazione interna dei dati di riga. La dimensione massima della riga viene applicata durante alcune fasi dell'esecuzione del job di query.

jobs.getQueryResult può restituire 20 MB di dati, a meno che non chieda esplicitamente di più tramite l'assistenza.

Una pagina è un sottoinsieme del numero totale di righe. Se i risultati sono più di una pagina di dati, i dati del risultato hanno una proprietà pageToken. Per recuperare la pagina successiva dei risultati, effettua un'altra chiamata list e includi il valore del token come parametro URL denominato pageToken.

Il metodo tabledata.list, utilizzato per sfogliare i dati delle tabelle, utilizza un valore di offset di riga o un token di pagina. Per informazioni, consulta la sezione Dati della tabella di navigazione.

I seguenti esempi mostrano un paging tramite i dati delle tabelle BigQuery.

C#

Prima di provare questo esempio, segui le istruzioni di configurazione di C# nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery C# .


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

Prima di provare questo esempio, segui le istruzioni di configurazione di Java nella guida rapida di BigQuery all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Java di BigQuery.

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

Prima di provare questo esempio, segui le istruzioni per la configurazione di Go nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Go.

Le librerie client di Google Cloud per Go impagina automaticamente per impostazione predefinita, quindi non è necessario implementare autonomamente l'impaginazione, ad esempio:

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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js nella guida rapida di BigQuery utilizzando le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Node.js.

Le librerie client di Cloud per Node.js impaginano automaticamente per impostazione predefinita, quindi non devi implementarle manualmente, ad esempio:

// 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

Prima di provare questo esempio, segui le istruzioni per la configurazione di PHP nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery PHP.

L'impaginazione viene eseguita automaticamente in Librerie client di Cloud per PHP utilizzando la funzione di generazione rows, che recupera la pagina successiva di risultati durante l'iterazione.

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

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Python per BigQuery.

Le librerie client di Cloud per Python impagina automaticamente per impostazione predefinita, quindi non è necessario implementare tu stesso l'impaginazione, ad esempio:


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

Prima di provare questo esempio, segui le istruzioni per la configurazione di Ruby nella guida rapida di BigQuery all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Ruby.

L'impaginazione viene eseguita automaticamente nelle librerie client di Cloud per Ruby utilizzando Table#data e 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

Richiedere pagine arbitrarie ed evitare chiamate a elenchi ridondanti

Quando vai indietro o passi a pagine arbitrarie con valori pageToken memorizzati nella cache, è possibile che i dati nelle pagine siano cambiati dall'ultima visualizzazione, ma non vi è alcuna indicazione chiara che i dati possano essere cambiati. Per mitigare i rischi, puoi utilizzare la proprietà etag.

Ogni metodo collection.list (ad eccezione di Tabledata) restituisce una proprietà etag nel risultato. Questa proprietà è un hash dei risultati della pagina che può essere utilizzato per verificare se la pagina è cambiata dall'ultima richiesta. Quando effettui una richiesta a BigQuery con un valore ETag, BigQuery confronta il valore ETag con il valore ETag restituito dall'API e risponde in base alla corrispondenza dei valori ETag. Per evitare chiamate ridondanti negli elenchi, puoi utilizzare gli ETag nel seguente modo:

  • Per restituire valori dell'elenco se i valori sono cambiati.

    Se vuoi restituire una pagina di valori di un elenco solo se i valori sono cambiati, puoi effettuare una chiamata a un elenco con un ETag memorizzato in precedenza utilizzando l'intestazione HTTP "if-none-match"". Se l'ETag fornito non corrisponde all'ETag sul server, BigQuery restituisce una pagina con nuovi valori per l'elenco. Se gli ETag corrispondono, BigQuery restituisce un codice di stato HTTP 304 Not Modified e nessun valore. Un esempio può essere una pagina web in cui gli utenti possono inserire periodicamente informazioni archiviate in BigQuery. Se non vengono apportate modifiche ai tuoi dati, puoi evitare di effettuare chiamate a elenchi ridondanti con BigQuery utilizzando l'intestazione if-none-match con ETag.

  • Per restituire valori elenco se i valori non sono cambiati.

    Se vuoi restituire una pagina di valori di elenco solo se i valori di tale elenco non sono cambiati, puoi utilizzare l'intestazione HTTP "if-match"". BigQuery corrisponde ai valori ETag e restituisce la pagina dei risultati se i risultati non sono cambiati o restituisce un risultato 412 "Precondition"Failed" se la pagina è cambiata.

Nota: anche se gli ETag sono un ottimo modo per evitare di effettuare chiamate ridondanti con gli elenchi, puoi applicare gli stessi metodi per identificare eventuali oggetti modificati. Ad esempio, puoi eseguire una richiesta Get per una tabella specifica e utilizzare gli ETag per determinare se la tabella è cambiata prima di restituire la risposta completa.

Eseguire una ricerca tramite i risultati della query

Ogni query viene scritta in una tabella di destinazione. Se non viene fornita una tabella di destinazione, l'API BigQuery completa automaticamente la proprietà della tabella di destinazione con un riferimento a una tabella temporanea anonima.

API

Leggi il campo jobs.config.query.destinationTable per determinare la tabella in cui sono stati scritti i risultati delle query. Chiama il tabledata.list per leggere i risultati della query.

Java

Prima di provare questo esempio, segui le istruzioni di configurazione di Java nella guida rapida di BigQuery all'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Java di BigQuery.

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());
    }
  }
}

Node.js

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js nella guida rapida di BigQuery utilizzando le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API BigQuery Node.js.

// 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

Il metodo QueryJob.result restituisce un'iterazione dei risultati della query. In alternativa,

  1. Leggi la proprietà QueryJob.destination. Se questa proprietà non è configurata, l'API imposta un riferimento a una tabella anonima temporanea.
  2. Scarica lo schema della tabella con il metodo Client.get_table.
  3. Crea un'iterazione su tutte le righe della tabella di destinazione con il metodo Client.list_rows.

Prima di provare questo esempio, segui le istruzioni di configurazione di Python nella guida rapida di BigQuery con le librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Python per BigQuery.


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"]))