Usa la API de transmisión heredada

En este documento, se describe cómo transmitir datos a BigQuery mediante el método heredado tabledata.insertAll.

Para los proyectos nuevos, recomendamos usar la API de Storage Write de BigQuery en lugar del método tabledata.insertAll. La API de Storage Write tiene precios más bajos y funciones más sólidas, incluida la semántica de entrega del tipo “exactamente una vez”. Si vas a migrar un proyecto existente del método tabledata.insertAll a la API de Storage Write, te recomendamos que selecciones la transmisión predeterminada. El método tabledata.insertAll aún es totalmente compatible.

Antes de comenzar

  1. Asegúrate de tener acceso de escritura al conjunto de datos que contiene tu tabla de destino. La tabla debe existir antes de comenzar la escritura de datos, a menos que estés usando tablas de plantillas Para obtener más información sobre las tablas de plantillas, consulta Crear tablas automáticamente con tablas de plantillas.

  2. Verifica la Política de cuota de transmisión de datos.

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. La transmisión no está disponible a través del nivel gratuito. Si intentas usar la transmisión sin habilitar la facturación, recibirás el error siguiente: BigQuery: Streaming insert is not allowed in the free tier.

  5. Otorga funciones de Identity and Access Management (IAM) que les brindan a los usuarios los permisos necesarios para realizar cada tarea de este documento.

Permisos necesarios

Para transmitir datos a BigQuery, necesitas los siguientes permisos de IAM:

  • bigquery.tables.updateData (te permite insertar datos en la tabla)
  • bigquery.tables.get (te permite obtener metadatos de tablas)
  • bigquery.datasets.get (te permite obtener metadatos de conjuntos de datos)
  • bigquery.tables.create (obligatorio si usas una tabla de plantillas para crear la tabla de forma automática)

Cada uno de los siguientes roles predefinidos de IAM incluye los permisos que necesitas para transmitir datos a BigQuery:

  • roles/bigquery.dataEditor
  • roles/bigquery.dataOwner
  • roles/bigquery.admin

Para obtener más información sobre las funciones de IAM y los permisos en BigQuery, consulta Funciones y permisos predefinidos.

Transmite datos a 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. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para C#.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.


using Google.Cloud.BigQuery.V2;

public class BigQueryTableInsertRows
{
    public void TableInsertRows(
        string projectId = "your-project-id",
        string datasetId = "your_dataset_id",
        string tableId = "your_table_id"
    )
    {
        BigQueryClient client = BigQueryClient.Create(projectId);
        BigQueryInsertRow[] rows = new BigQueryInsertRow[]
        {
            // The insert ID is optional, but can avoid duplicate data
            // when retrying inserts.
            new BigQueryInsertRow(insertId: "row1") {
                { "name", "Washington" },
                { "post_abbr", "WA" }
            },
            new BigQueryInsertRow(insertId: "row2") {
                { "name", "Colorado" },
                { "post_abbr", "CO" }
            }
        };
        client.InsertRows(datasetId, tableId, rows);
    }
}

Go

Antes de probar este ejemplo, sigue las instrucciones de configuración para Go incluidas 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 Go.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// Item represents a row item.
type Item struct {
	Name string
	Age  int
}

// Save implements the ValueSaver interface.
// This example disables best-effort de-duplication, which allows for higher throughput.
func (i *Item) Save() (map[string]bigquery.Value, string, error) {
	return map[string]bigquery.Value{
		"full_name": i.Name,
		"age":       i.Age,
	}, bigquery.NoDedupeID, nil
}

// insertRows demonstrates inserting data into a table using the streaming insert mechanism.
func insertRows(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: %w", err)
	}
	defer client.Close()

	inserter := client.Dataset(datasetID).Table(tableID).Inserter()
	items := []*Item{
		// Item implements the ValueSaver interface.
		{Name: "Phred Phlyntstone", Age: 32},
		{Name: "Wylma Phlyntstone", Age: 29},
	}
	if err := inserter.Put(ctx, items); err != nil {
		return err
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java incluidas 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.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryError;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.InsertAllRequest;
import com.google.cloud.bigquery.InsertAllResponse;
import com.google.cloud.bigquery.TableId;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// Sample to inserting rows into a table without running a load job.
public class TableInsertRows {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    // Create a row to insert
    Map<String, Object> rowContent = new HashMap<>();
    rowContent.put("booleanField", true);
    rowContent.put("numericField", "3.14");
    // TODO(developer): Replace the row id with a unique value for each row.
    String rowId = "ROW_ID";
    tableInsertRows(datasetName, tableName, rowId, rowContent);
  }

  public static void tableInsertRows(
      String datasetName, String tableName, String rowId, Map<String, Object> rowContent) {
    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();

      // Get table
      TableId tableId = TableId.of(datasetName, tableName);

      // Inserts rowContent into datasetName:tableId.
      InsertAllResponse response =
          bigquery.insertAll(
              InsertAllRequest.newBuilder(tableId)
                  // More rows can be added in the same RPC by invoking .addRow() on the builder.
                  // You can omit the unique row ids to disable de-duplication.
                  .addRow(rowId, rowContent)
                  .build());

      if (response.hasErrors()) {
        // If any of the insertions failed, this lets you inspect the errors
        for (Map.Entry<Long, List<BigQueryError>> entry : response.getInsertErrors().entrySet()) {
          System.out.println("Response error: \n" + entry.getValue());
        }
      }
      System.out.println("Rows successfully inserted into table");
    } catch (BigQueryException e) {
      System.out.println("Insert operation not performed \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js incluidas 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 Node.js.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

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

async function insertRowsAsStream() {
  // Inserts the JSON objects into my_dataset:my_table.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';
  const rows = [
    {name: 'Tom', age: 30},
    {name: 'Jane', age: 32},
  ];

  // Insert data into a table
  await bigquery.dataset(datasetId).table(tableId).insert(rows);
  console.log(`Inserted ${rows.length} rows`);
}

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. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para PHP.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

use Google\Cloud\BigQuery\BigQueryClient;

/**
 * Stream data into bigquery
 *
 * @param string $projectId The project Id of your Google Cloud Project.
 * @param string $datasetId The BigQuery dataset ID.
 * @param string $tableId The BigQuery table ID.
 * @param string $data Json encoded data For eg,
 *    $data = json_encode([
 *       "field1" => "value1",
 *       "field2" => "value2",
 *    ]);
 */
function stream_row(
    string $projectId,
    string $datasetId,
    string $tableId,
    string $data
): void {
    // instantiate the bigquery table service
    $bigQuery = new BigQueryClient([
      'projectId' => $projectId,
    ]);
    $dataset = $bigQuery->dataset($datasetId);
    $table = $dataset->table($tableId);

    $data = json_decode($data, true);
    $insertResponse = $table->insertRows([
      ['data' => $data],
      // additional rows can go here
    ]);
    if ($insertResponse->isSuccessful()) {
        print('Data streamed into BigQuery successfully' . PHP_EOL);
    } else {
        foreach ($insertResponse->failedRows() as $row) {
            foreach ($row['errors'] as $error) {
                printf('%s: %s' . PHP_EOL, $error['reason'], $error['message']);
            }
        }
    }
}

Python

Antes de probar este ejemplo, 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. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

from google.cloud import bigquery

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

# TODO(developer): Set table_id to the ID of table to append to.
# table_id = "your-project.your_dataset.your_table"

rows_to_insert = [
    {"full_name": "Phred Phlyntstone", "age": 32},
    {"full_name": "Wylma Phlyntstone", "age": 29},
]

errors = client.insert_rows_json(table_id, rows_to_insert)  # Make an API request.
if errors == []:
    print("New rows have been added.")
else:
    print("Encountered errors while inserting rows: {}".format(errors))

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. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Ruby.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

require "google/cloud/bigquery"

def table_insert_rows dataset_id = "your_dataset_id", table_id = "your_table_id"
  bigquery = Google::Cloud::Bigquery.new
  dataset  = bigquery.dataset dataset_id
  table    = dataset.table table_id

  row_data = [
    { name: "Alice", value: 5  },
    { name: "Bob",   value: 10 }
  ]
  response = table.insert row_data

  if response.success?
    puts "Inserted rows successfully"
  else
    puts "Failed to insert #{response.error_rows.count} rows"
  end
end

No es necesario que propagues el campo insertID cuando insertes filas. En el siguiente ejemplo, se muestra cómo evitar el envío de un insertID para cada fila cuando se realiza una transmisión.

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java incluidas 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.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryError;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.InsertAllRequest;
import com.google.cloud.bigquery.InsertAllResponse;
import com.google.cloud.bigquery.TableId;
import com.google.common.collect.ImmutableList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// Sample to insert rows without row ids in a table
public class TableInsertRowsWithoutRowIds {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    tableInsertRowsWithoutRowIds(datasetName, tableName);
  }

  public static void tableInsertRowsWithoutRowIds(String datasetName, String tableName) {
    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.
      final BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
      // Create rows to insert
      Map<String, Object> rowContent1 = new HashMap<>();
      rowContent1.put("stringField", "Phred Phlyntstone");
      rowContent1.put("numericField", 32);
      Map<String, Object> rowContent2 = new HashMap<>();
      rowContent2.put("stringField", "Wylma Phlyntstone");
      rowContent2.put("numericField", 29);
      InsertAllResponse response =
          bigquery.insertAll(
              InsertAllRequest.newBuilder(TableId.of(datasetName, tableName))
                  // No row ids disable de-duplication, and also disable the retries in the Java
                  // library.
                  .setRows(
                      ImmutableList.of(
                          InsertAllRequest.RowToInsert.of(rowContent1),
                          InsertAllRequest.RowToInsert.of(rowContent2)))
                  .build());

      if (response.hasErrors()) {
        // If any of the insertions failed, this lets you inspect the errors
        for (Map.Entry<Long, List<BigQueryError>> entry : response.getInsertErrors().entrySet()) {
          System.out.println("Response error: \n" + entry.getValue());
        }
      }
      System.out.println("Rows successfully inserted into table without row ids");
    } catch (BigQueryException e) {
      System.out.println("Insert operation not performed \n" + e.toString());
    }
  }
}

Python

Antes de probar este ejemplo, 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. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

from google.cloud import bigquery

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

# TODO(developer): Set table_id to the ID of table to append to.
# table_id = "your-project.your_dataset.your_table"

rows_to_insert = [
    {"full_name": "Phred Phlyntstone", "age": 32},
    {"full_name": "Wylma Phlyntstone", "age": 29},
]

errors = client.insert_rows_json(
    table_id, rows_to_insert, row_ids=[None] * len(rows_to_insert)
)  # Make an API request.
if errors == []:
    print("New rows have been added.")
else:
    print("Encountered errors while inserting rows: {}".format(errors))

Envía datos de fecha y hora

Para los campos de fecha y hora, formatea los datos en el método tabledata.insertAll de la siguiente manera:

Tipo Formato
DATE Una string con el formato "YYYY-MM-DD"
DATETIME Una string con el formato "YYYY-MM-DD [HH:MM:SS]"
TIME Una string con el formato "HH:MM:SS"
TIMESTAMP El número de segundos desde 1970-01-01 (época de Unix) o una string con el formato "YYYY-MM-DD HH:MM[:SS]".

Envía datos del rango

Para los campos con tipo RANGE<T>, formatea los datos en el método tabledata.insertAll como un objeto JSON con dos campos, start y end. Los valores faltantes o NULL para los campos start y end representan límites no delimitados. Estos campos deben tener el mismo formato JSON compatible de tipo T, en el que T puede ser uno de DATE, DATETIME y TIMESTAMP.

En el siguiente ejemplo, el campo f_range_date representa una columna RANGE<DATE> en una tabla. Se inserta una fila en esta columna mediante la API tabledata.insertAll.

{
    "f_range_date": {
        "start": "1970-01-02",
        "end": null
    }
}

Transmite la disponibilidad de los datos

Los datos están disponibles para el análisis en tiempo real mediante consultas de GoogleSQL inmediatamente después de que BigQuery confirma de forma correcta una solicitud tabledata.insertAll.

Las filas transmitidas recientemente a una tabla particionada por tiempo de transferencia tienen un valor NULL de forma temporal para la seudocolumna _PARTITIONTIME. Para esas filas, BigQuery asigna el valor final no NULL de la columna PARTITIONTIME en segundo plano, por lo general, dentro de unos minutos. En casos excepcionales, esto puede tardar hasta 90 minutos.

Es posible que algunas filas transmitidas recientemente no estén disponibles para la copia de tablas, por lo general, durante unos minutos. En casos excepcionales, esto puede tardar hasta 90 minutos. A fin de comprobar si los datos están disponibles para la copia de la tabla, verifica la respuesta tables.get de una sección llamada streamingBuffer. Si no aparece la sección streamingBuffer, tus datos estarán disponibles para copiarlos. También puedes usar el campo streamingBuffer.oldestEntryTime para identificar la antigüedad de los registros en el búfer de transmisión.

Anulación de duplicación de mejor esfuerzo

Cuando proporcionas insertId para una fila insertada, BigQuery usa este ID a fin de admitir la anulación de duplicación de mejor esfuerzo durante un minuto. Esto significa que, si transmites la misma fila con el mismo insertId más de una vez dentro de ese período en la misma tabla, BigQuery podría deduplicar varios casos de esa fila y conserva solo uno de ellos.

El sistema espera que las filas proporcionadas con insertId idénticas también sean idénticas. Si dos filas tienen insertId idénticas, no determina qué fila conserva BigQuery.

La deduplicación es para las situaciones de reintentos de un sistema distribuido en las que no hay forma de determinar el estado de una inserción de transmisión en ciertas condiciones de error, como errores de red entre tu sistema y BigQuery o errores internos en BigQuery Si vuelves a realizar una inserción, usa el mismo insertId en el mismo conjunto de filas para que BigQuery intente anular la duplicación tus datos. Para obtener más información, consulta Solución de problemas de inserciones de transmisión.

La anulación de duplicación que ofrece BigQuery es el mejor esfuerzo y no se debe confiar en ella como un mecanismo para garantizar la ausencia de duplicados en tus datos. Además, BigQuery puede disminuir la calidad de la anulación de duplicación de mejor esfuerzo en cualquier momento a fin de garantizar una mayor confiabilidad y disponibilidad para tus datos.

Si tienes requisitos estrictos de anulación de duplicación para tus datos, Google Cloud Datastore es un servicio alternativo que admite transacciones.

Inhabilita la deduplicación de mejor esfuerzo

La anulación de duplicación de mejor esfuerzo se inhabilita si no propagas el campo insertId para cada fila insertada. Esta es la forma recomendada de insertar datos.

Apache Beam y Dataflow

Si quieres inhabilitar la anulación de duplicación de mejor esfuerzo cuando usas el conector de E/S de BigQuery de Apache Beam para Java, usa el método ignoreInsertIds().

Quita los duplicados manualmente

Para asegurarte de que no existan filas duplicadas una vez que hayas terminado la transmisión, usa el siguiente proceso manual:

  1. Agrega el insertId como una columna en el esquema de tu tabla y el valor insertId en los datos de cada fila.
  2. Una vez que se haya detenido la transmisión, realiza la siguiente consulta para verificar si hay duplicados:

    #standardSQL
    SELECT
      MAX(count) FROM(
      SELECT
        ID_COLUMN,
        count(*) as count
      FROM
        `TABLE_NAME`
      GROUP BY
        ID_COLUMN)

    Si el resultado es mayor que 1, existen duplicados.
  3. Para quitar duplicados, ejecuta la siguiente consulta. Especifica una tabla de destino, inhabilita los resultados acoplados y permite resultados grandes.

    #standardSQL
    SELECT
      * EXCEPT(row_number)
    FROM (
      SELECT
        *,
        ROW_NUMBER()
              OVER (PARTITION BY ID_COLUMN) row_number
      FROM
        `TABLE_NAME`)
    WHERE
      row_number = 1

Notas sobre la consulta para quitar duplicados:

  • La estrategia más segura para la consulta sobre quitar duplicados es dirigirse a una tabla nueva. De manera alternativa, puedes dirigir la tabla de origen con la disposición de escritura WRITE_TRUNCATE.
  • La consulta de eliminación de duplicados agrega una columna row_number con el valor 1 al final del esquema de la tabla. La consulta usa una declaración SELECT * EXCEPT de GoogleSQL para excluir la columna row_number de la tabla de destino. El prefijo #standardSQL habilita GoogleSQL para esta consulta. De manera alternativa, puedes seleccionar por nombres de columna específicos para omitir esta columna.
  • Para consultar datos en vivo con duplicados que se quitaron, también puedes crear una vista sobre tu tabla mediante la consulta de eliminación de duplicados. Ten en cuenta que los costos de consulta con respecto a la vista se calcularán en función de las columnas seleccionadas en tu vista, lo que puede dar como resultado tamaños analizados de bytes grandes.

Transmite a tablas particionadas por tiempo

Cuando transmites datos a una tabla particionada por tiempo, cada partición tiene un búfer de transmisión. El búfer de transmisión se conserva cuando realizas un trabajo de copia, consulta o carga que reemplaza una partición mediante la configuración de la propiedad writeDisposition como WRITE_TRUNCATE. Si deseas quitar el búfer de transmisión, verifica que esté vacío mediante una llamada a tables.get en la partición.

Partición por tiempo de transferencia

Cuando transmites a una tabla particionada por tiempo de transferencia, BigQuery deduce la partición de destino a partir de la hora UTC actual.

Los datos recién llegados se colocan temporalmente en la partición __UNPARTITIONED__ mientras se encuentran en el búfer de transmisión. Cuando hay suficientes datos no particionados, BigQuery los particiona en la partición correcta. Sin embargo, no hay un ANS para el tiempo que tardan los datos en salir de la partición __UNPARTITIONED__. Por lo tanto, una consulta puede excluir los datos en el búfer de transmisión de una consulta mediante el filtrado de los valores NULL desde la partición __UNPARTITIONED__ con una de las seudocolumnas (_PARTITIONTIMEo _PARTITIONDATE según tu tipo de datos preferido).

Si transmites datos a una tabla particionada diaria, puedes anular la fecha de inferencia si proporcionas un decorador de partición como parte de la solicitud insertAll. Incluye el decorador en el parámetro tableId. Por ejemplo, puedes transmitir a la partición correspondiente al 2021-03-01 para la tabla table1 con el decorador de partición:

table1$20210301

Cuando transmites con un decorador de partición, puedes transmitir a particiones dentro de los últimos 31 días pasados y 16 días futuros en relación con la fecha actual, según la hora UTC actual. A fin de escribir en particiones para fechas fuera de estos límites permitidos, usa un trabajo de carga o de consulta, como se describe en Anexa y reemplaza datos de tablas particionadas.

La transmisión mediante un decorador de particiones solo se admite para tablas particionadas por día. No es compatible con tablas particionadas por hora, mes o año.

Para realizar pruebas, puedes usar el comando de la CLI bq insert de la herramienta de línea de comandos de bq. Por ejemplo, con el siguiente comando, se transmite una sola fila a una partición para la fecha del 1 de enero de 2017 ($20170101) en una tabla particionada llamada mydataset.mytable:

echo '{"a":1, "b":2}' | bq insert 'mydataset.mytable$20170101'

Partición de columnas por unidad de tiempo

Puedes transmitir datos a una tabla particionada en una columna DATE, DATETIME o TIMESTAMP que esté entre 5 años en el pasado y 1 año en el futuro. Los datos fuera de este rango se rechazan.

Cuando los datos se transmiten, inicialmente se colocan en la partición __UNPARTITIONED__. Cuando hay suficientes datos no particionados, BigQuery vuelve a particionarlos de forma automática y los coloca en la partición adecuada. Sin embargo, no hay un ANS para el tiempo que tardan los datos en salir de la partición __UNPARTITIONED__.

  • Nota: Las particiones diarias se procesan de manera distinta que las particiones por hora, mes y año. Solo se extraen los datos fuera del período (de los últimos 7 días a 3 días futuros) para la partición UNPARTITIONED, a la espera de que se vuelvan a particionar. Por otro lado, en la tabla particionada por hora, los datos siempre se extraen a la partición UNPARTITIONED y, luego, se vuelven a particionar.

Crea tablas automáticamente con tablas de plantillas

Las tablas de plantillas proporcionan un mecanismo para dividir una tabla lógica en varias tablas más pequeñas a fin de crear conjuntos de datos más pequeños (por ejemplo, según el ID del usuario). Las tablas de plantillas tienen ciertas limitaciones que se describen a continuación. En cambio, las tablas particionadas y las tablas agrupadas son las formas recomendadas de lograr este comportamiento.

Para usar una tabla de plantilla a través de la API de BigQuery, agrega un parámetro templateSuffix a tu solicitud insertAll. Para la herramienta de línea de comandos de bq, agrega la marca template_suffix a tu comando insert. Si BigQuery detecta un parámetro templateSuffix o la marca template_suffix, trata la tabla de destino como una plantilla base. Crea una tabla nueva que comparte el mismo esquema que la tabla de destino y tiene un nombre que incluye el sufijo especificado:

<targeted_table_name> + <templateSuffix>

Cuando uses una tabla de plantillas, evita la sobrecarga de crear cada tabla individualmente y de especificar el esquema para cada tabla. Solo necesitas crear una plantilla única y suministrar sufijos diferentes a fin de que BigQuery pueda crear las nuevas tablas por ti. BigQuery coloca las tablas en el mismo proyecto y conjunto de datos.

Las tablas que se crean mediante las tablas de plantillas suelen estar disponibles en unos pocos segundos. En raras ocasiones pueden tardar más en estar disponibles.

Cambia el esquema de la tabla de plantilla

Si cambias un esquema de tabla de plantilla, todas las tablas que se generen después usarán el esquema actualizado. Las tablas generadas anteriormente no se ven afectadas, a menos que la tabla existente aún tenga un búfer de transmisión.

Para las tablas existentes que todavía tienen un búfer de transmisión, si modificas el esquema de la tabla de la plantilla de una manera compatible con versiones anteriores, el esquema de esas tablas generadas de forma activa también se actualiza. Sin embargo, si modificas el esquema de la tabla de plantillas de una manera no compatible con versiones anteriores, se pierden todos los datos almacenados en el búfer que usen el esquema anterior. Además, no puedes transmitir datos nuevos a tablas generadas existentes que usen el esquema anterior, pero que ahora no es compatible.

Después de cambiar un esquema de tabla de plantilla, espera hasta que los cambios se hayan propagado antes de intentar insertar nuevos datos o consultar tablas generadas. Las solicitudes para insertar nuevos campos deben ser correctas en unos pocos minutos. Los intentos de consultar los nuevos campos pueden requerir más tiempo, hasta 90 minutos.

Si deseas cambiar el esquema de una tabla generada, no cambies el esquema hasta que la transmisión por medio de la tabla de plantilla haya terminado y la sección de estadísticas de transmisión de la tabla generada falte en la respuesta de tables.get(), lo que indica que no hay datos almacenados en el búfer en la tabla.

Las tablas particionadas y las tablas agrupadas no se ven afectadas por las limitaciones anteriores y son el mecanismo recomendado.

Detalles de la tabla de plantilla

Valor del sufijo de plantilla
El valor templateSuffix (o --template_suffix) debe contener solo letras (a-z, A-Z), números (0-9) o guiones bajos (_). La longitud máxima combinada del nombre de la tabla y el sufijo de la tabla es de 1,024 caracteres.
Cuota

Las tablas de plantillas están sujetas a limitaciones de cuota de transmisión. Tu proyecto puede realizar hasta 10 tablas por segundo con tablas de plantillas, similar a la API de tables.insert. Esta cuota solo se aplica a las tablas que se están creando, no a las tablas que se están modificando.

Si tu aplicación necesita crear más de 10 tablas por segundo, te recomendamos usar tablas agrupadas en clústeres. Por ejemplo, puedes colocar el ID de la tabla de alta cardinalidad en la columna de clave de una sola tabla de agrupamiento en clústeres.

Tiempo de vida

La tabla generada hereda su fecha de caducidad del conjunto de datos. Al igual que con los datos de transmisión normales, las tablas generadas no se pueden copiar de inmediato.

Anulación de duplicación

La anulación de duplicación solo ocurre entre referencias uniformes a una tabla de destino. Por ejemplo, si realizas una transmisión simultánea a una tabla generada con ambas tablas de plantillas y un comando regular insertAll, no se produce ninguna anulación de duplicación entre las filas insertadas por las tablas de plantillas y un comando regular insertAll.

Vistas

La tabla de plantillas y las tablas generadas no deben ser vistas.

Soluciona problemas de inserciones de transmisión

En las secciones siguientes, se analiza cómo solucionar errores que ocurren cuando transmites datos a BigQuery mediante la API de transmisión heredada. Si deseas obtener más información para resolver errores de cuota de las inserciones de transmisión, consulta Errores de cuota de inserción de transmisión.

Códigos de respuesta HTTP de falla

Si recibes un código de respuesta HTTP de falla, como un error de red, no hay forma de saber si la inserción de transmisión se realizó de forma correcta. Si solo intentas volver a enviar la solicitud, puede que dé como resultado filas duplicadas en tu tabla. Para proteger tu tabla de la duplicación, establece la propiedad insertId cuando envíes tu solicitud. BigQuery usa la propiedad insertId para la anulación de la duplicación.

Si recibes un error de permiso, un error de nombre de tabla no válido o un error de cuota excedida, no se insertan filas y la solicitud en su totalidad falla.

Códigos de respuesta HTTP de éxito

Incluso si recibes un código de respuesta HTTP correcto, deberás verificar la propiedad insertErrors de la respuesta para determinar si las inserciones de fila se completaron, ya que es posible que BigQuery solo haya insertado de forma correcta algunas de las filas. Es posible encontrar una de las siguientes excepciones:

  • Todas las filas se insertaron correctamente. Si la propiedad insertErrors es una lista vacía, todas las filas se insertaron de forma correcta.
  • Algunas filas se insertaron correctamente. Excepto en los casos en los que no coincide el esquema en alguna de las filas, las filas indicadas en la propiedad insertErrors no se insertan, y todas las demás se insertan de forma correcta. La propiedad errors contiene información detallada sobre por qué falló cada fila no exitosa. La propiedad index indica el índice de filas basado en 0 de la solicitud a la que se aplica el error.
  • Ninguna de las filas se insertó correctamente. Si BigQuery descubre que el esquema de filas individuales no coincide en la solicitud, no se inserta ninguna de las filas y se muestra una entrada insertErrors para cada fila, incluso las filas que no tuvieron problemas de coincidencia del esquema. Las filas cuyos esquemas coincidieron tendrán un error con la propiedad reason establecida en stopped y se pueden volver a enviar como están. Las filas que tuvieron un error incluyen información detallada sobre la falta de coincidencia del esquema. A fin de obtener información sobre los tipos de búferes de protocolo admitidos para cada tipo de datos de BigQuery, consulta Conversiones de tipos de datos.

Errores de metadatos para inserción de transmisión

Debido a que la API de transmisión de BigQuery está diseñada para un gran volumen de inserciones, las modificaciones a la exhibición de metadatos de la tabla subyacente presentan coherencia eventual cuando se interactúa con el sistema de transmisión. En la mayoría de los casos, los cambios de metadatos se propagan en minutos, pero, durante este período, las respuestas de la API pueden mostrar el estado inconsistente de la tabla.

A continuación, se describen algunas situaciones:

  • Cambios en el esquema. Modificar el esquema de una tabla que recibió inserciones de transmisión hace poco puede dar como resultado errores de no coincidencia del esquema, ya que es posible que el sistema de transmisión no reciba el cambio del esquema de inmediato.
  • Creación o eliminación de tablas. Transmitir a una tabla inexistente mostrará la variación de una respuesta notFound. Puede que las inserciones de transmisión posteriores no reconozcan de inmediato la creación de una tabla como respuesta. De manera similar, borrar o volver a crear una tabla puede crear un período en el que las inserciones de transmisión se envíen de manera efectiva a la tabla anterior. Es posible que las inserciones de transmisión no estén presentes en la tabla nueva.
  • Truncamiento de tabla. Truncar los datos de una tabla (mediante un trabajo de consulta que use writeDisposition de WRITE_TRUNCATE) puede causar que se descarten las inserciones posteriores durante el período de coherencia.

Datos faltantes o no disponibles

Las inserciones de transmisión residen de manera temporal en el almacenamiento con optimización de escritura, que tiene características de disponibilidad diferentes de las del almacenamiento administrado. Ciertas operaciones en BigQuery no interactúan con el almacenamiento optimizado para escritura, como los trabajos de copia de tablas y los métodos de API como tabledata.list. Los datos de transmisión recientes no estarán presentes en la tabla de destino ni en el resultado.