Este documento descreve como transmitir dados para o BigQuery através do método tabledata.insertAll
antigo.
Para novos projetos, recomendamos que use a
API BigQuery Storage Write em vez do método
tabledata.insertAll
. A API Storage Write tem preços mais baixos e funcionalidades mais robustas, incluindo a semântica de entrega exatamente uma vez. Se estiver a migrar um projeto existente do método tabledata.insertAll
para a API Storage Write, recomendamos que selecione a stream predefinida. O método tabledata.insertAll
continua a ser totalmente suportado.
Antes de começar
Certifique-se de que tem acesso de escrita ao conjunto de dados que contém a tabela de destino. A tabela tem de existir antes de começar a escrever dados na mesma, a menos que esteja a usar tabelas de modelos. Para mais informações sobre tabelas de modelos, consulte o artigo Crie tabelas automaticamente com tabelas de modelos.
Consulte a política de quotas para dados de streaming.
-
Verify that billing is enabled for your Google Cloud project.
Conceda funções de gestão de identidade e acesso (IAM) que dão aos utilizadores as autorizações necessárias para realizar cada tarefa neste documento.
O streaming não está disponível através do nível gratuito. Se tentar usar o streaming sem ativar a faturação, recebe o seguinte erro: BigQuery: Streaming insert is not allowed in the free tier.
Autorizações necessárias
Para transmitir dados para o BigQuery, precisa das seguintes autorizações do IAM:
bigquery.tables.updateData
(permite-lhe inserir dados na tabela)bigquery.tables.get
(permite obter metadados de tabelas)bigquery.datasets.get
(permite obter metadados do conjunto de dados)bigquery.tables.create
(obrigatório se usar uma tabela de modelo para criar a tabela automaticamente)
Cada uma das seguintes funções predefinidas do IAM inclui as autorizações de que precisa para transmitir dados em stream para o BigQuery:
roles/bigquery.dataEditor
roles/bigquery.dataOwner
roles/bigquery.admin
Para mais informações acerca das funções e autorizações do IAM no BigQuery, consulte o artigo Funções e autorizações predefinidas.
Transmita dados para o BigQuery
C#
Antes de experimentar este exemplo, siga as C#instruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API C# BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Go
Antes de experimentar este exemplo, siga as Goinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Go BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Java
Antes de experimentar este exemplo, siga as Javainstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Java BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Node.js
Antes de experimentar este exemplo, siga as Node.jsinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Node.js BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
PHP
Antes de experimentar este exemplo, siga as PHPinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API PHP BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Python
Antes de experimentar este exemplo, siga as Pythoninstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Python BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Ruby
Antes de experimentar este exemplo, siga as Rubyinstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Ruby BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Não tem de preencher o campo insertID
quando insere linhas.
O exemplo seguinte mostra como evitar o envio de um insertID
para cada linha quando faz streaming.
Java
Antes de experimentar este exemplo, siga as Javainstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Java BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Python
Antes de experimentar este exemplo, siga as Pythoninstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Python BigQuery documentação de referência.
Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para bibliotecas de cliente.
Envie dados de data e hora
Para campos de data e hora, formate os dados no método tabledata.insertAll
da seguinte forma:
Tipo | Formato |
---|---|
DATE |
Uma string no formato "YYYY-MM-DD" |
DATETIME |
Uma string no formato "YYYY-MM-DD [HH:MM:SS]" |
TIME |
Uma string no formato "HH:MM:SS" |
TIMESTAMP |
O número de segundos desde 01/01/1970 (a época Unix) ou uma string
no formato "YYYY-MM-DD HH:MM[:SS]" |
Envie dados de intervalo
Para campos com o tipo RANGE<T>
, formate os dados no método tabledata.insertAll
como um objeto JSON com dois campos, start
e end
.
Os valores em falta ou NULL para os campos start
e end
representam limites ilimitados.
Estes campos têm de ter o mesmo formato JSON suportado do tipo T
, em que T
pode ser um dos seguintes: DATE
, DATETIME
e TIMESTAMP
.
No exemplo seguinte, o campo f_range_date
representa uma coluna RANGE<DATE>
numa tabela. É inserida uma linha nesta coluna através da API tabledata.insertAll
.
{
"f_range_date": {
"start": "1970-01-02",
"end": null
}
}
Disponibilidade de dados da stream
Os dados estão disponíveis para análise em tempo real através de consultas GoogleSQL imediatamente após o BigQuery acusar a receção com êxito de um pedido tabledata.insertAll
.
As linhas transmitidas recentemente para uma tabela particionada por tempo de ingestão têm temporariamente um valor NULL para a pseudocoluna _PARTITIONTIME
. Para essas linhas, o BigQuery atribui o valor final não NULL da coluna PARTITIONTIME
em segundo plano, normalmente, no prazo de alguns minutos. Em casos raros, esta ação pode demorar até 90 minutos.
Algumas linhas transmitidas recentemente podem não estar disponíveis para cópia de tabelas, normalmente durante alguns minutos. Em casos raros, esta ação pode demorar até 90 minutos. Para ver se os dados estão disponíveis para a cópia de tabelas, verifique a resposta tables.get
para uma secção denominada streamingBuffer
.
Se a secção streamingBuffer
estiver ausente, os seus dados estão disponíveis para cópia.
Também pode usar o campo streamingBuffer.oldestEntryTime
para identificar a idade dos registos no buffer de streaming.
Eliminação de duplicados dentro do possível
Quando fornece insertId
para uma linha inserida, o BigQuery usa este ID para suportar a remoção de duplicados da melhor forma possível durante um máximo de um minuto. Ou seja, se transmitir a mesma linha com o mesmo insertId
mais do que uma vez nesse período, o BigQuery pode remover as duplicadas das várias ocorrências dessa linha, retendo apenas uma dessas ocorrências.
O sistema espera que as linhas fornecidas com insertId
s idênticos também sejam idênticas. Se duas linhas tiverem insertId
s idênticos, não é possível determinar qual linha o BigQuery preserva.
A remoção de duplicados destina-se geralmente a cenários de repetição num sistema distribuído onde não existe forma de determinar o estado de uma inserção de streaming em determinadas condições de erro, como erros de rede entre o seu sistema e o BigQuery ou erros internos no BigQuery.
Se repetir uma inserção, use o mesmo insertId
para o mesmo conjunto de linhas, para que o BigQuery possa tentar remover duplicados dos seus dados. Para mais
informações, consulte o artigo Resolva problemas de inserções de streaming.
A remoção de duplicados oferecida pelo BigQuery é baseada no melhor esforço e não deve ser usada como um mecanismo para garantir a ausência de duplicados nos seus dados. Além disso, o BigQuery pode degradar a qualidade da desduplicação de melhor esforço em qualquer altura para garantir uma maior fiabilidade e disponibilidade dos seus dados.
Se tiver requisitos de remoção de duplicados rigorosos para os seus dados, o Armazenamento de dados do Google Cloud é um serviço alternativo que suporta transações.
Desativar a remoção de duplicados com base no melhor esforço
Pode desativar a eliminação de duplicados da melhor forma não preenchendo o campo insertId
para cada linha inserida. Esta é a forma recomendada de inserir dados.
Apache Beam e Dataflow
Para desativar a eliminação de duplicados da melhor forma quando usa o conetor BigQuery I/O do Apache Beam para Java, use o método ignoreInsertIds()
.
Remover duplicados manualmente
Para garantir que não existem linhas duplicadas após a conclusão do streaming, use o seguinte processo manual:
- Adicione
insertId
como uma coluna no esquema da tabela e inclua o valorinsertId
nos dados de cada linha. - Depois de a transmissão em streaming parar, execute a seguinte consulta para verificar se existem duplicados:
Se o resultado for superior a 1, existem duplicados.#standardSQL SELECT MAX(count) FROM( SELECT ID_COLUMN, count(*) as count FROM `TABLE_NAME` GROUP BY ID_COLUMN)
- Para remover duplicados, execute a seguinte consulta. Especifique
uma tabela de destino, permita resultados grandes e desative o nivelamento 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 acerca da consulta de remoção de duplicados:
- A estratégia mais segura para a consulta de remoção de duplicados é segmentar uma nova tabela.
Em alternativa, pode segmentar a tabela de origem com a disposição de escrita
WRITE_TRUNCATE
. - A consulta de remoção de duplicados adiciona uma coluna
row_number
com o valor1
ao final do esquema da tabela. A consulta usa uma declaraçãoSELECT * EXCEPT
do GoogleSQL para excluir a colunarow_number
da tabela de destino. O prefixo#standardSQL
ativa o GoogleSQL para esta consulta. Em alternativa, pode selecionar nomes de colunas específicos para omitir esta coluna. - Para consultar dados em direto com duplicados removidos, também pode criar uma vista sobre a sua tabela através da consulta de remoção de duplicados. Tenha em atenção que os custos das consultas relativas à vista são calculados com base nas colunas selecionadas na sua vista, o que pode resultar em tamanhos de bytes analisados grandes.
Faça stream para tabelas particionadas por tempo
Quando transmite dados para uma tabela particionada por tempo, cada partição tem um buffer de streaming. O buffer de streaming é retido quando executa uma tarefa de carregamento, consulta ou cópia que substitui uma partição definindo a propriedade writeDisposition
como WRITE_TRUNCATE
. Se quiser remover o buffer de streaming, verifique se o buffer de streaming está vazio chamando tables.get
na partição.
Particionamento por tempo de ingestão
Quando faz streaming para uma tabela particionada por tempo de ingestão, o BigQuery infere a partição de destino a partir da hora UTC atual.
Os dados recebidos recentemente são colocados temporariamente na partição __UNPARTITIONED__
enquanto estão no buffer de streaming. Quando existem dados não particionados suficientes, o BigQuery particiona os dados na partição correta. No entanto, não existe um SLA para o tempo que os dados demoram a sair da partição __UNPARTITIONED__
. Uma consulta pode excluir dados no buffer de streaming de uma consulta filtrando os valores NULL
da partição __UNPARTITIONED__
através de uma das pseudocolunas (_PARTITIONTIME
ou _PARTITIONDATE
, consoante o tipo de dados preferido).
Se estiver a transmitir dados para uma tabela particionada diariamente, pode substituir a inferência de data fornecendo um decorador de partição como parte do pedido.insertAll
Inclua o decorator no parâmetro tableId
. Por exemplo, pode
fazer stream para a partição correspondente a 2021-03-01 para a tabela table1
usando o
decorador de partição:
table1$20210301
Quando faz streaming com um decorador de partições, pode fazer streaming para partições nos últimos 31 dias e nos 16 dias seguintes em relação à data atual, com base na hora UTC atual. Para escrever em partições para datas fora destes limites permitidos, use um trabalho de carregamento ou de consulta, conforme descrito no artigo Anexar e substituir dados de tabelas particionadas.
O streaming com um decorador de partição só é suportado para tabelas particionadas diariamente. Não é suportado para tabelas particionadas por hora, mês ou ano.
Para testes, pode usar a ferramenta de linhas de comando bq
comando CLI bq insert
.
Por exemplo, o seguinte comando transmite uma única linha para uma partição para a data 1 de janeiro de 2017 ($20170101
) numa tabela particionada denominada mydataset.mytable
:
echo '{"a":1, "b":2}' | bq insert 'mydataset.mytable$20170101'
Partição de colunas de unidades de tempo
Pode transmitir dados para uma tabela particionada numa coluna DATE
, DATETIME
ou TIMESTAMP
que esteja entre 10 anos no passado e 1 ano no futuro.
Os dados fora deste intervalo são rejeitados.
Quando os dados são transmitidos, são inicialmente colocados na partição __UNPARTITIONED__
. Quando existem dados não particionados suficientes, o BigQuery
reparticiona automaticamente os dados, colocando-os na partição adequada.
No entanto, não existe um SLA para o tempo que os dados demoram a sair da partição __UNPARTITIONED__
.
- Nota: as partições diárias são processadas de forma diferente das partições por hora, mensais e anuais. Apenas os dados fora do intervalo de datas (últimos 7 dias a 3 dias futuros) são extraídos para a partição UNPARTITIONED, aguardando a repartição. Por outro lado, para uma tabela particionada por hora, os dados são sempre extraídos para a partição UNPARTITIONED e, posteriormente, reparticionados.
Crie tabelas automaticamente com tabelas de modelos
As tabelas de modelos oferecem um mecanismo para dividir uma tabela lógica em muitas tabelas mais pequenas para criar conjuntos de dados mais pequenos (por exemplo, por ID do utilizador). As tabelas de modelos têm várias limitações descritas abaixo. Em alternativa, as tabelas particionadas e as tabelas agrupadas são as formas recomendadas de alcançar este comportamento.
Para usar uma tabela de modelo através da API BigQuery, adicione um parâmetro templateSuffix
ao seu pedido insertAll
. Para a ferramenta de linhas de comando bq, adicione a flag template_suffix
ao comando insert
. Se o BigQuery detetar um parâmetro templateSuffix
ou a flag template_suffix
, trata a tabela segmentada como um modelo
base. Cria uma nova tabela que partilha o mesmo esquema que a tabela segmentada e tem um nome que inclui o sufixo especificado:
<targeted_table_name> + <templateSuffix>
Ao usar uma tabela de modelo, evita a sobrecarga de criar cada tabela individualmente e especificar o esquema para cada tabela. Só tem de criar um único modelo e fornecer diferentes sufixos para que o BigQuery possa criar as novas tabelas por si. O BigQuery coloca as tabelas no mesmo projeto e conjunto de dados.
Normalmente, as tabelas criadas através de tabelas de modelos ficam disponíveis em poucos segundos. Em casos raros, podem demorar mais tempo a ficar disponíveis.
Altere o esquema da tabela de modelos
Se alterar o esquema de uma tabela de modelo, todas as tabelas geradas posteriormente usam o esquema atualizado. As tabelas geradas anteriormente não são afetadas, a menos que a tabela existente ainda tenha um buffer de streaming.
Para tabelas existentes que ainda tenham um buffer de streaming, se modificar o esquema da tabela de modelo de forma retrocompatível, o esquema dessas tabelas geradas com streaming ativo também é atualizado. No entanto, se modificar o esquema da tabela de modelos de forma não compatível com versões anteriores, todos os dados em buffer que usam o esquema antigo são perdidos. Além disso, não pode transmitir novos dados para tabelas geradas existentes que usem o esquema antigo, mas agora incompatível.
Depois de alterar o esquema de uma tabela de modelos, aguarde até que as alterações sejam propagadas antes de tentar inserir novos dados ou consultar as tabelas geradas. Os pedidos de inserção de novos campos devem ser bem-sucedidos dentro de alguns minutos. As tentativas de consultar os novos campos podem exigir um tempo de espera mais longo, até 90 minutos.
Se quiser alterar o esquema de uma tabela gerada, não altere o esquema até que o streaming através da tabela de modelos tenha parado e a secção de estatísticas de streaming da tabela gerada esteja ausente da resposta tables.get()
, o que indica que não existem dados em buffer na tabela.
As tabelas particionadas e as tabelas agrupadas não sofrem das limitações anteriores e são o mecanismo recomendado.
Detalhes da tabela de modelos
- Valor do sufixo do modelo
- O valor
templateSuffix
(ou--template_suffix
) tem de conter apenas letras (a-z, A-Z), números (0-9) ou sublinhados (_). O comprimento combinado máximo do nome da tabela e do sufixo da tabela é de 1024 carateres. - Quota
As tabelas de modelos estão sujeitas a limitações de quota de streaming. O seu projeto pode criar até 10 tabelas por segundo com tabelas de modelos, semelhantes à API
tables.insert
. Esta quota aplica-se apenas às tabelas que estão a ser criadas e não às tabelas que estão a ser modificadas.Se a sua aplicação precisar de criar mais de 10 tabelas por segundo, recomendamos a utilização de tabelas agrupadas. Por exemplo, pode colocar o ID da tabela de alta cardinalidade na coluna de chave de uma única tabela de agrupamento.
- Tempo de vida
A tabela gerada herda o respetivo tempo de expiração do conjunto de dados. Tal como acontece com os dados de streaming normais, não é possível copiar imediatamente as tabelas geradas.
- Remoção de duplicados
A eliminação de duplicados só ocorre entre referências uniformes a uma tabela de destino. Por exemplo, se transmitir simultaneamente para uma tabela gerada usando tabelas de modelos e um comando
insertAll
normal, não ocorre desduplicação entre as linhas inseridas pelas tabelas de modelos e um comandoinsertAll
normal.- Visualizações
A tabela de modelos e as tabelas geradas não devem ser vistas.
Resolva problemas de inserções de streaming
As secções seguintes abordam a resolução de problemas de erros que ocorrem quando faz stream de dados para o BigQuery através da API Legacy Streaming. Para mais informações sobre como resolver erros de quota para inserções de streaming, consulte Erros de quota de inserções de streaming.
Códigos de resposta HTTP de falha
Se receber um código de resposta HTTP de falha, como um erro de rede, não existe forma de saber se a inserção de streaming foi bem-sucedida. Se tentar reenviar o pedido, pode acabar com linhas duplicadas na tabela. Para ajudar a
proteger a sua tabela contra duplicações, defina a propriedade insertId
quando
enviar o seu pedido. O BigQuery usa a propriedade insertId
para remover duplicações.
Se receber um erro de autorização, um erro de nome de tabela inválido ou um erro de quota excedida, não são inseridas linhas e todo o pedido falha.
Códigos de resposta HTTP de êxito
Mesmo que receba um
código de resposta HTTP com êxito, tem de verificar a propriedade insertErrors
da resposta para determinar se as inserções de linhas foram bem-sucedidas, uma vez que é possível que o BigQuery só tenha tido êxito parcial na inserção das linhas. Pode encontrar um dos seguintes cenários:
- Todas as linhas foram inseridas com êxito. Se a propriedade
insertErrors
for uma lista vazia, todas as linhas foram inseridas com êxito. - Algumas linhas foram inseridas com êxito. Exceto nos casos em que existe uma
incompatibilidade de esquema em qualquer uma das linhas, as linhas indicadas na propriedade
insertErrors
não são inseridas, e todas as outras linhas são inseridas com êxito. A propriedadeerrors
contém informações detalhadas sobre o motivo da falha de cada linha sem êxito. A propriedadeindex
indica o índice da linha com base em 0 do pedido ao qual o erro se aplica. - Nenhuma das linhas foi inserida com êxito. Se o BigQuery encontrar uma incompatibilidade de esquema em linhas individuais no pedido, nenhuma das linhas é inserida e é devolvida uma entrada
insertErrors
para cada linha, mesmo as linhas que não tinham uma incompatibilidade de esquema. As linhas que não tinham uma incompatibilidade de esquema têm um erro com a propriedadereason
definida comostopped
e podem ser reenviadas tal como estão. As linhas que falharam incluem informações detalhadas sobre a incompatibilidade de esquema. Para saber mais acerca dos tipos de protocolo buffer suportados para cada tipo de dados do BigQuery, consulte Conversões de tipos de dados.
Erros de metadados para inserções de streaming
Uma vez que a API de streaming do BigQuery foi concebida para taxas de inserção elevadas, as modificações aos metadados da tabela subjacente são eventualmente consistentes quando interagem com o sistema de streaming. Na maioria das vezes, as alterações aos metadados são propagadas em poucos minutos, mas durante este período, as respostas da API podem refletir o estado inconsistente da tabela.
Alguns cenários incluem:
- Alterações ao esquema. A modificação do esquema de uma tabela que recebeu recentemente inserções de streaming pode causar respostas com erros de incompatibilidade de esquemas, porque o sistema de streaming pode não detetar imediatamente a alteração do esquema.
- Criação/eliminação de tabelas. O streaming para uma tabela inexistente devolve uma variação de uma resposta
notFound
. Uma tabela criada na resposta pode não ser reconhecida imediatamente por inserções de streaming subsequentes. Da mesma forma, a eliminação ou a recriação de uma tabela pode criar um período em que as inserções de streaming são efetivamente enviadas para a tabela antiga. As inserções de streaming podem não estar presentes na nova tabela. - Truncatura de tabelas. A truncagem dos dados de uma tabela (através de uma tarefa de consulta que usa writeDisposition de WRITE_TRUNCATE) pode, de igual modo, fazer com que as inserções subsequentes durante o período de consistência sejam ignoradas.
Dados em falta/indisponíveis
As inserções de streaming residem temporariamente no armazenamento otimizado para escrita, que tem características de disponibilidade diferentes do armazenamento gerido. Determinadas operações no BigQuery não interagem com o armazenamento otimizado para escrita, como tarefas de cópia de tabelas e métodos de API como tabledata.list
.
Os dados de streaming recentes não estão presentes na tabela de destino nem na saída.