En este documento se describe cómo enviar datos a BigQuery mediante el método antiguo tabledata.insertAll
.
En el caso de los proyectos nuevos, recomendamos usar la API Storage Write de BigQuery en lugar del método tabledata.insertAll
. La API Storage Write tiene precios más bajos y funciones más sólidas, incluida la semántica de entrega "exactamente una vez". Si vas a migrar un proyecto del método tabledata.insertAll
a la API Storage Write, te recomendamos que selecciones el flujo predeterminado. El método tabledata.insertAll
sigue siendo totalmente compatible.
Antes de empezar
Asegúrate de que tienes acceso de escritura al conjunto de datos que contiene la tabla de destino. La tabla debe existir antes de que empiece a escribir datos en ella, a menos que utilice tablas de plantilla. Para obtener más información sobre las tablas de plantilla, consulta el artículo Crear tablas automáticamente con tablas de plantilla.
Consulta la política de cuotas de datos de streaming.
-
Verify that billing is enabled for your Google Cloud project.
Concede roles de gestión de identidades y accesos (IAM) que proporcionen a los usuarios los permisos necesarios para realizar cada tarea de este documento.
El streaming no está disponible en el nivel gratuito. Si intentas usar el streaming sin habilitar la facturación, recibirás el siguiente error: BigQuery: Streaming insert is not allowed in the free tier.
Permisos obligatorios
Para transmitir datos a BigQuery, necesitas los siguientes permisos de gestión de identidades y accesos:
bigquery.tables.updateData
(permite insertar datos en la tabla)bigquery.tables.get
(permite obtener metadatos de tablas)bigquery.datasets.get
(permite obtener metadatos de conjuntos de datos)bigquery.tables.create
(obligatorio si usas una tabla de plantilla para crear la tabla automáticamente)
Cada uno de los siguientes roles de gestión de identidades y accesos predefinidos 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 los roles y permisos de gestión de identidades y accesos en BigQuery, consulta el artículo sobre roles y permisos predefinidos.
Transmitir datos a BigQuery
C#
Antes de probar este ejemplo, sigue las C#instrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API C# de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Go
Antes de probar este ejemplo, sigue las Goinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Go de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Java
Antes de probar este ejemplo, sigue las Javainstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Java de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Node.js
Antes de probar este ejemplo, sigue las Node.jsinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Node.js de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
PHP
Antes de probar este ejemplo, sigue las PHPinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API PHP de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Python
Antes de probar este ejemplo, sigue las Pythoninstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Python de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Ruby
Antes de probar este ejemplo, sigue las Rubyinstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Ruby de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
No es necesario que rellenes el campo insertID
cuando insertes filas.
En el siguiente ejemplo se muestra cómo evitar enviar un insertID
por cada fila al transmitir datos.
Java
Antes de probar este ejemplo, sigue las Javainstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Java de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Python
Antes de probar este ejemplo, sigue las Pythoninstrucciones de configuración de la guía de inicio rápido de BigQuery con bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Python de BigQuery.
Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación para bibliotecas de cliente.
Enviar datos de fecha y hora
En el caso de los campos de fecha y hora, dé formato a los datos con el método tabledata.insertAll
de la siguiente manera:
Tipo | Formato |
---|---|
DATE |
Cadena con el formato "YYYY-MM-DD" |
DATETIME |
Cadena con el formato "YYYY-MM-DD [HH:MM:SS]" |
TIME |
Cadena con el formato "HH:MM:SS" |
TIMESTAMP |
Número de segundos transcurridos desde el 1 de enero de 1970 (el inicio del registro de tiempo de Unix) o una cadena
con el formato "YYYY-MM-DD HH:MM[:SS]" |
Enviar datos de intervalo
En los campos de tipo RANGE<T>
, dé formato a los datos del método tabledata.insertAll
como un objeto JSON con dos campos, start
y end
.
Los valores que faltan o son NULL en los campos start
y end
representan límites no definidos.
Estos campos deben tener el mismo formato JSON admitido de tipo T
, donde T
puede ser DATE
, DATETIME
o TIMESTAMP
.
En el siguiente ejemplo, el campo f_range_date
representa una columna RANGE<DATE>
de una tabla. Se inserta una fila en esta columna mediante la API tabledata.insertAll
.
{
"f_range_date": {
"start": "1970-01-02",
"end": null
}
}
Disponibilidad de datos de streaming
Los datos están disponibles para el análisis en tiempo real mediante consultas de GoogleSQL inmediatamente después de que BigQuery confirme correctamente una solicitud tabledata.insertAll
.
Las filas que se han insertado recientemente en una tabla con particiones por tiempo de ingestión tienen temporalmente un valor NULL en la pseudocolumna _PARTITIONTIME
. En el caso de estas filas, BigQuery asigna el valor final no NULL de la columna PARTITIONTIME
en segundo plano, normalmente en unos minutos. En casos excepcionales, este proceso puede tardar hasta 90 minutos.
Es posible que algunas filas transmitidas recientemente no estén disponibles para copiarse en la tabla durante unos minutos. En casos excepcionales, este proceso puede tardar hasta 90 minutos. Para ver si hay datos disponibles para copiar la tabla, consulta la respuesta tables.get
de una sección llamada streamingBuffer
.
Si no aparece la sección streamingBuffer
, significa que tus datos se pueden copiar.
También puedes usar el campo streamingBuffer.oldestEntryTime
para identificar la antigüedad de los registros en el búfer de streaming.
Anulación de duplicados mejor posible
Cuando proporcionas insertId
para una fila insertada, BigQuery usa este ID para admitir la eliminación de duplicados con el mejor esfuerzo posible durante un minuto como máximo. Es decir, si envías la misma fila con el mismo insertId
más de una vez en ese periodo a la misma tabla, BigQuery podría eliminar los duplicados de esa fila y conservar solo una de las ocurrencias.
El sistema espera que las filas proporcionadas con insertId
s idénticos también lo sean. Si dos filas tienen insertId
s idénticos, no se puede determinar qué fila conserva BigQuery.
La deduplicación suele utilizarse en situaciones de reintento en un sistema distribuido en el que no se puede determinar el estado de una inserción de transmisión en determinadas condiciones de error, como errores de red entre su sistema y BigQuery o errores internos en BigQuery.
Si vuelves a intentar una inserción, usa el mismo insertId
para el mismo conjunto de filas, de forma que BigQuery pueda intentar eliminar los duplicados de tus datos. Para obtener más información, consulta Solucionar problemas con las inserciones de transmisión.
La desduplicación que ofrece BigQuery se realiza de la mejor forma posible, pero no se debe considerar un mecanismo que garantice la ausencia de duplicados en los datos. Además, BigQuery puede reducir la calidad de la desduplicación de mejor esfuerzo en cualquier momento para garantizar una mayor fiabilidad y disponibilidad de sus datos.
Si tienes requisitos estrictos de desduplicación de datos, Google Cloud Datastore es un servicio alternativo que admite transacciones.
Inhabilitar la anulación de duplicados mejor posible
Para inhabilitar la anulación de duplicados mejor posible, no rellenes el campo insertId
de cada fila insertada. Esta es la forma recomendada de insertar datos.
Apache Beam y Dataflow
Para inhabilitar la desduplicación con el mejor esfuerzo posible cuando uses el conector de E/S de BigQuery de Apache Beam para Java, usa el método ignoreInsertIds()
.
Eliminar duplicados manualmente
Para asegurarte de que no haya filas duplicadas después de completar la transmisión, sigue este proceso manual:
- Añada
insertId
como columna en el esquema de la tabla e incluya el valorinsertId
en los datos de cada fila. - Una vez que se haya detenido la emisión, realiza la siguiente consulta para comprobar si hay duplicados:
Si el resultado es mayor que 1, significa que hay duplicados.#standardSQL SELECT MAX(count) FROM( SELECT ID_COLUMN, count(*) as count FROM `TABLE_NAME` GROUP BY ID_COLUMN)
- Para eliminar los duplicados, ejecuta la siguiente consulta. Especifica
una tabla de destino, permite resultados grandes e inhabilita el acoplamiento de resultados.
#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 de retirada de duplicados:
- La estrategia más segura para la consulta de eliminación de duplicados es orientarla a una tabla nueva.
También puede orientar la tabla de origen con la disposición de escritura
WRITE_TRUNCATE
. - La consulta de eliminación de duplicados añade una columna
row_number
con el valor1
al final del esquema de la tabla. La consulta usa una declaraciónSELECT * EXCEPT
de GoogleSQL para excluir la columnarow_number
de la tabla de destino. El prefijo#standardSQL
habilita GoogleSQL para esta consulta. También puede seleccionar nombres de columna específicos para omitir esta columna. - Para consultar datos activos sin duplicados, también puedes crear una vista de tu tabla con la consulta de eliminación de duplicados. Ten en cuenta que los costes de las consultas en la vista se calculan en función de las columnas seleccionadas en la vista, lo que puede dar lugar a tamaños de bytes analizados grandes.
Transmitir datos a tablas con particiones por tiempo
Cuando transmite datos a una tabla particionada por tiempo, cada partición tiene un búfer de transmisión. El búfer de streaming se conserva cuando realizas un trabajo de carga, consulta o copia que sobrescribe una partición al definir la propiedad writeDisposition
en WRITE_TRUNCATE
. Si quieres eliminar el búfer de streaming, comprueba que esté vacío llamando a tables.get
en la partición.
Partición por hora de ingestión
Cuando transmite datos a una tabla con particiones por hora de ingestión, BigQuery infiere la partición de destino a partir de la hora UTC actual.
Los datos que llegan se colocan temporalmente en la partición __UNPARTITIONED__
mientras están en el búfer de streaming. Cuando hay suficientes datos sin particionar, BigQuery los particiona en la partición correcta. Sin embargo, no hay ningún SLA que indique cuánto tiempo tardan los datos en salir de la partición __UNPARTITIONED__
. Una consulta puede excluir datos del búfer de streaming si filtra los valores NULL
de la partición __UNPARTITIONED__
mediante una de las pseudocolumnas (_PARTITIONTIME
o _PARTITIONDATE
, según el tipo de datos que prefieras).
Si estás transmitiendo datos a una tabla con particiones diarias, puedes anular la inferencia de la fecha proporcionando un decorador de partición como parte de la solicitud insertAll
. Incluye el decorador en el parámetro tableId
. Por ejemplo, puedes enviar datos a la partición correspondiente al 1 de marzo del 2021 de la tabla table1
mediante el decorador de partición:
table1$20210301
Cuando se transmite contenido en streaming mediante un decorador de partición, se puede transmitir a particiones de los últimos 31 días y de los próximos 16 días con respecto a la fecha actual, según la hora UTC actual. Para escribir en particiones de fechas que estén fuera de estos límites permitidos, usa una tarea de carga o de consulta, tal como se describe en el artículo Añadir y sobrescribir datos de tablas con particiones.
Solo se admite la transmisión mediante un decorador de partición en tablas particionadas por día. No se admite en tablas particionadas por horas, meses o años.
Para hacer pruebas, puedes usar el comando de la CLI bq insert
de la herramienta de línea de comandos bq.
Por ejemplo, el siguiente comando transmite una sola fila a una partición de la fecha 1 de enero del 2017 ($20170101
) en una tabla con particiones llamada mydataset.mytable
:
echo '{"a":1, "b":2}' | bq insert 'mydataset.mytable$20170101'
Partición por columnas de unidades de tiempo
Puede transmitir datos a una tabla particionada por una columna DATE
, DATETIME
o TIMESTAMP
que esté entre 10 años en el pasado y 1 año en el futuro.
Los datos que estén fuera de este intervalo se rechazarán.
Cuando los datos se transmiten, se colocan inicialmente en la partición __UNPARTITIONED__
. Cuando hay suficientes datos sin particionar, BigQuery vuelve a particionarlos automáticamente y los coloca en la partición adecuada.
Sin embargo, no hay ningún SLA sobre el tiempo que tardan los datos en salir de la partición __UNPARTITIONED__
.
- Nota: Las particiones diarias se procesan de forma diferente a las particiones por hora, mensuales y anuales. Solo se extraen a la partición UNPARTITIONED los datos que no se encuentran en el intervalo de fechas (desde los últimos 7 días hasta los próximos 3 días) y se espera a que se vuelvan a particionar. Por otro lado, en el caso de las tablas con particiones por horas, los datos siempre se extraen a la partición UNPARTITIONED y, posteriormente, se vuelven a particionar.
Crear tablas automáticamente con tablas de plantilla
Las tablas de plantilla proporcionan un mecanismo para dividir una tabla lógica en muchas tablas más pequeñas con el fin de crear conjuntos de datos más pequeños (por ejemplo, por ID de usuario). Las tablas de plantillas tienen una serie de limitaciones que se describen a continuación. En su lugar, se recomienda usar tablas con particiones y tablas agrupadas en clústeres para conseguir este comportamiento.
Para usar una tabla de plantilla a través de la API de BigQuery, añade un parámetro templateSuffix
a tu solicitud insertAll
. En el caso de la herramienta de línea de comandos bq, añade la marca template_suffix
al comando insert
. Si BigQuery detecta un templateSuffix
parámetro o la marca template_suffix
, trata la tabla de destino como una plantilla base. Crea una tabla que comparte el mismo esquema que la tabla de destino y tiene un nombre que incluye el sufijo especificado:
<targeted_table_name> + <templateSuffix>
Si usas una tabla de plantilla, no tendrás que crear cada tabla individualmente ni especificar el esquema de cada una. Solo tienes que crear una plantilla y proporcionar diferentes sufijos para que BigQuery pueda crear las nuevas tablas. BigQuery coloca las tablas en el mismo proyecto y conjunto de datos.
Las tablas creadas con plantillas suelen estar disponibles en unos segundos. En contadas ocasiones, pueden tardar más en estar disponibles.
Cambiar el esquema de la tabla de la plantilla
Si cambia el esquema de una tabla de plantilla, todas las tablas que se generen posteriormente usarán el esquema actualizado. Las tablas generadas anteriormente no se ven afectadas, a menos que la tabla siga teniendo un búfer de streaming.
En el caso de las tablas que ya tienen un búfer de streaming, si modificas el esquema de la tabla de plantilla de forma retrocompatible, también se actualizará el esquema de las tablas generadas que se estén transmitiendo activamente. Sin embargo, si modificas el esquema de la tabla de la plantilla de forma que no sea compatible con versiones anteriores, se perderán los datos almacenados en búfer que utilicen el esquema antiguo. Además, no puedes transmitir datos nuevos a las tablas generadas que usen el esquema antiguo, que ahora es incompatible.
Después de cambiar el esquema de una tabla de plantilla, espera a que los cambios se propaguen antes de intentar insertar datos nuevos o consultar las tablas generadas. Las solicitudes para insertar campos nuevos deberían completarse en unos minutos. Las consultas de los nuevos campos pueden requerir un tiempo de espera más largo, de hasta 90 minutos.
Si quieres cambiar el esquema de una tabla generada, no lo hagas hasta que haya finalizado la transmisión a través de la tabla de plantilla y la sección de estadísticas de transmisión de la tabla generada no aparezca en la respuesta tables.get()
, lo que indica que no hay datos almacenados en la tabla.
Las tablas con particiones y las tablas agrupadas en clústeres no tienen las limitaciones anteriores y son el mecanismo recomendado.
Detalles de la tabla de plantilla
- Valor de sufijo de plantilla
- El valor de
templateSuffix
(o--template_suffix
) solo puede contener 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 1024 caracteres. - Cuota
Las tablas de plantillas están sujetas a las limitaciones de la cuota de streaming. Tu proyecto puede crear hasta 10 tablas por segundo con tablas de plantilla, de forma similar a la API
tables.insert
. Esta cuota solo se aplica a las tablas que se crean, no a las que se modifican.Si tu aplicación necesita crear más de 10 tablas por segundo, te recomendamos que uses 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 clustering.
- Tiempo de vida
La tabla generada hereda su tiempo de vencimiento del conjunto de datos. Al igual que con los datos de streaming normales, las tablas generadas no se pueden copiar inmediatamente.
- Anulación de duplicados
La anulación de duplicados solo se aplica entre referencias uniformes a una tabla de destino. Por ejemplo, si insertas datos simultáneamente en una tabla generada mediante tablas de plantilla y un comando
insertAll
normal, no se eliminarán los duplicados entre las filas insertadas por las tablas de plantilla y el comandoinsertAll
normal.- Vistas
La tabla de plantilla y las tablas generadas no deben ser vistas.
Solucionar problemas con las inserciones de streaming
En las siguientes secciones se explica cómo solucionar los errores que se producen al transmitir datos a BigQuery con la API Legacy streaming. Para obtener más información sobre cómo resolver los errores de cuota de inserción de transmisión, consulta el artículo Errores de cuota de inserción de transmisión.
Códigos de respuesta HTTP de error
Si recibes un código de respuesta HTTP de error, como un error de red, no hay forma de saber si la inserción de streaming se ha realizado correctamente. Si intentas volver a enviar la solicitud, es posible que se dupliquen las filas de la tabla. Para proteger tu tabla frente a duplicados, define la propiedad insertId
al enviar tu solicitud. BigQuery usa la propiedad insertId
para eliminar duplicados.
Si recibe un error de permiso, un error de nombre de tabla no válido o un error de cuota superada, no se insertará ninguna fila y toda la solicitud fallará.
Códigos de respuesta HTTP correctos
Aunque recibas un
código de respuesta HTTP correcto, tendrás que comprobar la propiedad insertErrors
de la respuesta para determinar si las inserciones de filas se han realizado correctamente, ya que es posible que BigQuery solo haya podido insertar las filas parcialmente. Puede que te encuentres en una de las siguientes situaciones:
- Todas las filas se han insertado correctamente. Si la propiedad
insertErrors
es una lista vacía, significa que todas las filas se han insertado correctamente. - Algunas filas se han insertado correctamente. Excepto en los casos en los que haya un error de coincidencia de esquema en alguna de las filas, las filas indicadas en la propiedad
insertErrors
no se insertan y todas las demás se insertan correctamente. La propiedaderrors
contiene información detallada sobre por qué se ha producido un error en cada fila. La propiedadindex
indica el índice de la fila de la solicitud (empezando por 0) a la que se aplica el error. - No se ha insertado ninguna fila correctamente. Si BigQuery detecta que el esquema no coincide en filas concretas de la solicitud, no se insertará ninguna fila y se devolverá una entrada
insertErrors
por cada fila, incluso por las que no tenían un esquema que no coincidía. Las filas que no tenían un error de incompatibilidad de esquemas tienen un error con la propiedadreason
definida comostopped
y se pueden volver a enviar tal cual. Las filas que no se han podido enviar incluyen información detallada sobre el error de incompatibilidad de esquemas. Para obtener información sobre los tipos de búfer de protocolo admitidos para cada tipo de datos de BigQuery, consulta Conversiones de tipos de datos.
Errores de metadatos de inserciones de transmisión
Como la API de transmisión de BigQuery se ha diseñado para ofrecer altas tasas de inserción, las modificaciones de los metadatos de la tabla subyacente son coherentes con el tiempo al interactuar con el sistema de transmisión. La mayoría de las veces, los cambios en los metadatos se propagan en cuestión de minutos, pero durante este periodo, las respuestas de la API pueden reflejar el estado incoherente de la tabla.
Algunos ejemplos son los siguientes:
- Cambios en el esquema. Si modificas el esquema de una tabla que ha recibido inserciones de streaming recientemente, se pueden producir respuestas con errores de discrepancia de esquema, ya que es posible que el sistema de streaming no detecte el cambio de esquema inmediatamente.
- Creación o eliminación de tablas. Si se transmite a una tabla que no existe, se devuelve una variación de la respuesta
notFound
. Es posible que una tabla creada en una respuesta no se reconozca inmediatamente en las inserciones de streaming posteriores. Del mismo modo, si se elimina o se vuelve a crear una tabla, puede haber un periodo en el que las inserciones de streaming se envíen a la tabla antigua. Es posible que las inserciones de streaming no estén presentes en la nueva tabla. - Truncamiento de tablas. De forma similar, truncar los datos de una tabla (mediante una tarea de consulta que utilice el valor WRITE_TRUNCATE de writeDisposition) puede provocar que se eliminen las inserciones posteriores durante el periodo de coherencia.
Faltan datos o no están disponibles
Las inserciones de streaming se almacenan temporalmente en el almacenamiento optimizado para escritura, que tiene características de disponibilidad diferentes a las del almacenamiento gestionado. Algunas operaciones de 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 streaming recientes no estarán presentes en la tabla de destino ni en la salida.