Desplázate por los datos de tablas

En este documento, se describe cómo desplazarse por los datos de tablas y los resultados de la consulta mediante la API de REST de BigQuery.

Desplázate por los resultados mediante la API

Todos los métodos *collection*.list muestran resultados paginados en determinadas circunstancias. La propiedad maxResults controla el número de resultados por página.

Método Criterios de paginación Valor maxResults predeterminado Valor maxResults máximo Valor maxFieldValues máximo
Tabledata.list Muestra resultados paginados si el tamaño de la respuesta supera los 10 MB1 de datos o más de las filas de maxResults. 100,000 Ilimitado Ilimitado
Todos los demás métodos *collection*.list Muestra resultados paginados si el tamaño de la respuesta supera las filas en maxResults, y también se encuentra por debajo de los límites máximos. 10,000 Ilimitado 300,000

Si el resultado es mayor que el límite de bytes o campos, el resultado se corta para ajustarlo al límite. Si una fila supera el límite de bytes o campos, tabledata.list puede mostrar hasta 100 MB de datos1, que es coherente con el límite máximo de tamaño de fila para los resultados de la consulta.

1 El tamaño de la fila es aproximado, ya que se basa en la representación interna de los datos de la fila. El tamaño máximo de la fila se aplica durante ciertas etapas de la ejecución del trabajo de consulta.

jobs.getQueryResult puede mostrar 20 MB de datos, a menos que de forma explícita se solicite una cantidad mayor mediante la asistencia.

Una página es un subconjunto de la cantidad total de filas. Si tus resultados ocupan más de una página de datos, los datos que resulten tendrán una propiedad pageToken. Para recuperar la página siguiente de resultados, haz otra llamada a list y, también, incluye el valor del token como un parámetro URL llamado pageToken.

El método tabledata.list, que se utiliza para desplazarse por los datos de la tabla, usa un valor de desplazamiento de fila o un token de página. Consulta la página sobre cómo explorar datos de tablas para obtener más información.

Los siguientes ejemplos muestran la paginación a través de los datos de tablas de BigQuery.

C#

Antes de probar este ejemplo, sigue las instrucciones de configuración para C# incluidas en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de C# de BigQuery.


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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

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

Comienza a usarlo

Antes de probar este ejemplo, sigue las instrucciones de configuración para Go que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de Go de BigQuery.

La biblioteca cliente de Cloud para Go se pagina automáticamente de forma predeterminada, por lo que no necesitas implementar la paginación, por ejemplo:

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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la Documentación de referencia de la API de Node.js de BigQuery.

La biblioteca cliente de Cloud para Node.js se pagina automáticamente de forma predeterminada, por lo que no necesitas implementar la paginación, por ejemplo:


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

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

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

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

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

PHP

Antes de probar este ejemplo, sigue las instrucciones de configuración para PHP incluidas en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de PHP de BigQuery.

La paginación se realiza de forma automática en las bibliotecas cliente de Cloud para PHP mediante la función de generador rows, que recupera la siguiente página de resultados durante la iteración.

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

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de Python de BigQuery.

La biblioteca cliente de Cloud para Python se pagina automáticamente de forma predeterminada, por lo que no necesitas implementar la paginación, por ejemplo:


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

Antes de probar este ejemplo, sigue las instrucciones de configuración para Ruby incluidas en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. A fin de obtener más información, consulta la documentación de referencia de la API de BigQuery para Ruby.

La paginación se realiza de forma automática en las bibliotecas cliente de Cloud para Ruby mediante Table#data y 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

Solicita páginas arbitrarias y evita llamadas redundantes a las listas

Cuando retrocedes la página o saltas a páginas arbitrarias con valores de pageToken almacenados en caché, es posible que los datos de tus páginas hayan cambiado desde la última vez que se vieron, aunque no hay un indicio claro de que así sea. Para mitigar este efecto, puedes usar la propiedad Etag.

Cada método collection.list (excepto Tabledata) muestra una propiedad Etag en el resultado. Esta propiedad genera un hash de los resultados de la página que se pueden usar para verificar si esta cambió desde la última solicitud. Cuando realizas una solicitud a BigQuery con un valor Etag, BigQuery compara el valor Etag con el valor de ETag que la API mostró y responde si esos valores coinciden. Puedes usar las ETag para evitar llamadas redundantes a las listas de las siguientes maneras:

  • Si solo deseas que se muestren los valores de la lista si los valores han cambiado:

    Si solo deseas que se muestre una página con los valores de la lista si los valores cambiaron, puedes crear una llamada a la lista con un ETag almacenado con anterioridad mediante el encabezado HTTP "if-none-match". Si el ETag que proporcionas no coincide con el ETag en el servidor, BigQuery muestra una página de valores de lista nuevos. Si los ETags coinciden, BigQuery muestra un resultado HTTP 304 "Not Modified" y no hay valores. Un ejemplo de esto podría ser una página web donde los usuarios pueden completar, de manera periódica, información que se encuentra almacenada en BigQuery. Puedes evitar hacer llamadas redundantes a las listas en BigQuery si no hay cambios en tus datos con el encabezado if-none-match con ETags.

  • Si solo deseas que se muestren los valores de la lista si los valores han cambiado:

    Si solo deseas que se muestre una página con los valores de la lista en caso de que los valores no hayan cambiado, puedes usar el encabezado HTTP "if-match". BigQuery hace coincidir los valores de los ETag y muestra la página de resultados si los resultados no han cambiado, o muestra un resultado 412 "Precondition Failed" si la página cambió.

Nota: A pesar de que los ETag son una excelente manera de evitar la realización de llamadas redundantes a las listas, puedes aplicar los mismos métodos para identificar si algún objeto cambió. Por ejemplo, puedes realizar una solicitud Get en una tabla específica y usar ETags para determinar si la tabla cambió antes de mostrar la respuesta completa.

Paginación a través de resultados de consultas

Cada consulta escribe en una tabla de destino. Si no se proporciona una tabla de destino, la API de BigQuery propaga automáticamente la propiedad de tabla de destino mediante la referencia a una tabla anónima temporal.

API

Lee el campo jobs.config.query.destinationTable para determinar la tabla en la que se escribieron los resultados de la consulta. Llama a tabledata.list para leer los resultados de la consulta.

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

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 runQueryPagination() {
    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));

      results
          .getNextPage()
          .iterateAll()
          .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));

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

Python

El método QueryJob.result muestra un iterable de los resultados de la consulta. O, como alternativa:

  1. Lee la propiedad QueryJob.destination. Si no se configura, la API establecerá esta propiedad como referencia a una tabla anónima temporal.
  2. Obtén el esquema de la tabla con el método Client.get_table.
  3. Crea un iterable en todas las filas de la tabla de destino con el método Client.list_rows.

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de Python de 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"]))