SELECT e INSERT em uma tabela no Google BigQuery, incluindo conjuntos de dados públicos. A estrutura da tabela é inferida automaticamente do esquema da tabela do BigQuery.
A leitura usa a API REST do BigQuery (tabledata.list); portanto, apenas tabelas nativas podem ser lidas (não é possível ler visões, visões materializadas nem tabelas externas). A gravação usa inserções por streaming (tabledata.insertAll), o que exige que o faturamento esteja habilitado para o projeto.
Sintaxe
Argumentos
Os argumentos
project, dataset, table e access_token também podem ser fornecidos no formato key = value; os argumentos posicionais preenchem essas posições nessa ordem, e especificar um argumento tanto por posição quanto como chave (ou repetir a mesma chave) gera um erro.
Os seguintes argumentos podem ser especificados no formato key = value (ou como chaves de uma coleção nomeada):
Autenticação
- Token de acesso. Qualquer token de acesso OAuth 2.0 válido, por exemplo, obtido com
gcloud auth print-access-token. Os tokens expiram rapidamente (geralmente após uma hora), portanto, esse método é mais adequado para uso interativo. - Chave de conta de serviço (recomendada para servidores). Forneça o conteúdo de um arquivo de chave criado no Google Cloud IAM usando o argumento
service_account_key. O ClickHouse assina um JWT com a chave e o troca por um token de acesso, renovando-o automaticamente. - Token de atualização. Forneça
client_id,client_secreterefresh_token, por exemplo, extraídos de~/.config/gcloud/application_default_credentials.jsonapós executargcloud auth application-default login.
BigQuery ou CREATE TABLE ... AS bigquery(...)) é registrada como dependência da coleção. Portanto, DROP NAMED COLLECTION é bloqueado enquanto a tabela existir.
Mapeamento de tipos de dados
Notas:
- O
DATETIMEdo BigQuery não tem fuso horário; ele é mapeado paraDateTime64(6, 'UTC')para que o valor exibido não dependa do fuso horário do servidor. - Um
RECORDNULLABLEé mapeado paraNullable(Tuple(...)), preservando umNULLde registro completo comoNULL, em vez de reduzi-lo a umTuplede valores padrão. Um arrayNULL(ou vazio) se torna um array vazio, poisArraynão pode estar dentro deNullableno ClickHouse. Um array do BigQuery não pode conter elementosNULL(ARRAY<T>é equivalente aARRAY<T NOT NULL>); portanto, o tipo de elemento de um campoREPEATEDnão éNullable(Array(T)ouArray(Tuple(...))para um elementoRECORD). Um elementoNULLem uma respostatabledata.listé rejeitado como entrada malformada. - A leitura e a gravação de colunas
Nullable(Tuple(...))por meio da função de tabelabigqueryfuncionam sem configurações adicionais. A criação de uma tabela persistente com o mecanismoBigQueryque contenha essa coluna, seja com a estrutura inferida ou declarada explicitamente, requer a configuraçãoenable_nullable_tuple_type, assim como qualquer colunaNullable(Tuple). Ao declarar colunas explicitamente, um campoRECORDpode ser declarado como umTuple(...)simples para evitar essa configuração, ao custo de converter umNULLde registro completo em uma tupla padrão; a única diferença aceita em relação ao tipo inferido é remover oNullableque envolve oTuplede umRECORD, e somente nesse mesmo registro — a nulabilidade não pode ser movida para outro registro, interno ou externo. GEOGRAPHYé mapeado para Geometry. O BigQuery transfere um valorGEOGRAPHYcomo texto WKT, que é analisado como a alternativa correspondente deGeometry(umVariantdePoint,MultiPoint,Ring,LineString,MultiLineString,PolygoneMultiPolygon) na leitura e serializado novamente como WKT na gravação. UmaGEOMETRYCOLLECTIONe uma geometria vazia, comoPOINT EMPTY, não têm equivalente emGeometry; portanto, a leitura de uma linha que contenha esse valor gera um erro. ComoVariantjá comporta umNULL, um campoGEOGRAPHYNULLABLEé mapeado paraGeometry, e não paraNullable(Geometry), e oNULLcontinua sendo preservado na ida e volta.JSONé mapeado paraString, em vez do tipo de dados JSON, porque o tipoJSONdo ClickHouse aceita apenas um objeto ({...}) no nível superior, enquanto um valorJSONdo BigQuery pode ser qualquer valor JSON — um escalar, um array ounull. Portanto, uma tabela que contenha esses valores não poderia ser lida. Além disso,JSONnão pode ser envolvido emNullable, de modo que umNULLSQL em uma colunaNULLABLEnão seria preservado. O mapeamento paraStringnão perde dados; objetos de nível superior podem ser convertidos comCAST(value AS JSON).- Valores
BIGNUMERICcom mais de 38 dígitos na parte inteira não cabem emDecimal(76, 38)e geram um erro. - Valores
TIMESTAMPeDATEfora do intervalo deDateTime64/Date32(anos de 1900 a 2299) não são compatíveis. - Colunas
RANGEsão somente leitura.tabledata.insertAllespera um valorRANGE<T>como um objeto estruturado{start, end}, que não pode ser reconstruído a partir do mapeamento paraString; portanto, a inserção em uma colunaRANGEgera um erro. - Valores
INT64são enviados paratabledata.insertAllcomo strings decimais, pois a API interpreta números JSON como doubles e, caso contrário, corromperia valores fora de[-2^53 + 1, 2^53 - 1].
Exemplos
gcloud:
Limitações
- Somente tabelas nativas do BigQuery podem ser lidas. Views e tabelas externas exigem a execução de um job de consulta do BigQuery, o que esta função não faz.
- Colunas
RANGEpodem ser lidas (comoString), mas não gravadas: inserir em uma colunaRANGEgera um erro. - Um valor
GEOGRAPHYque seja umaGEOMETRYCOLLECTIONou uma geometria vazia não pode ser representado pelo tipoGeometry; portanto, a leitura de uma linha que contenha um desses valores gera um erro. Gravar umGeometryNULLem um campoGEOGRAPHYREQUIRED, ou como elemento de um campoGEOGRAPHYREPEATED, é rejeitado, pois o BigQuery não aceitaNULLnesses casos. - Os predicados não são enviados para baixo:
tabledata.listapenas lista as linhas de uma tabela e não tem nenhum parâmetro de filtragem (aceita opções de paginação, seleção de colunas e formato), e a filtragem exigiria a execução de um job de consulta do BigQuery, o que esta função não faz. Portanto, uma condiçãoWHEREé aplicada no ClickHouse depois que as linhas são baixadas; use a seleção de colunas para reduzir os dados transferidos. - Por outro lado, um
LIMITreduz a quantidade de dados lidos. As páginas são solicitadas sob demanda, commaxResultsdefinido comomax_block_size, e nenhuma página adicional é solicitada quando a consulta já tem linhas suficientes. Para umLIMIT ntrivial (semWHERE,GROUP BY,ORDER BYe comnmenor quemax_block_size), o ClickHouse reduzmax_block_sizeparan, de modo que é feita exatamente uma solicitação para exatamentenlinhas; caso contrário, a leitura é interrompida no primeiro limite de página após o limite, excedendo-o em menos de uma página. - A leitura fica vinculada ao schema observado no momento da análise da consulta, passando a lista explícita de colunas para
tabledata.list. Para uma leitura muito ampla cuja lista de colunas excederia o limite de comprimento da URL da solicitação (por exemplo,SELECT *de uma tabela com milhares de colunas), a consulta é rejeitada em vez de ser executada sem essa vinculação (uma leitura sem vinculação poderia ser desalinhada por uma alteração concorrente no schema); selecione menos colunas para que a lista caiba. O mesmo limite de comprimento da URL é verificado antes de cada solicitação paginada (cada página inclui umpageTokenopaco); portanto, uma leitura cujas páginas posteriores não caibam no limite é rejeitada com o mesmo erro, em vez de falhar no meio do processo. - Se a tabela do BigQuery for alterada depois que seu schema tiver sido lido, a consulta será rejeitada em vez de retornar ou gravar dados incompatíveis silenciosamente: o schema atual é buscado novamente e comparado ao analisado imediatamente antes de uma leitura e novamente antes que um
INSERTtransmita sua primeira linha. A janela restante — uma alteração no schema entre essa verificação e as solicitações subsequentes — não pode ser eliminada, pois o schema e os dados são buscados por solicitações REST separadas. - A comparação é feita com o snapshot do schema usado na análise da consulta, obtido quando a função de tabela resolve sua estrutura ou, no caso de uma tabela persistente (uma tabela com engine
BigQueryou uma tabela criada comCREATE TABLE ... AS bigquery(...), que persiste suas colunas da mesma forma), em sua primeira leitura ou gravação apósCREATE,ATTACHou uma reinicialização do servidor. Os metadados da tabela persistem as colunas mapeadas do ClickHouse, e não o schema do BigQuery; portanto, uma alteração no schema feita enquanto a tabela estava desanexada (ou o servidor estava inativo) é adotada pela próxima consulta em vez de ser rejeitada: as colunas declaradas ainda são validadas em relação ao schema atual, e as linhas são decodificadas com base nele, de modo que uma alteração que preserve os tipos mapeados do ClickHouse (STRINGparaBYTES, por exemplo) seja lida segundo as regras do novo tipo, mantendo o mesmo tipo de coluna. - As linhas gravadas com inserts de streaming chegam ao buffer de streaming do BigQuery e podem levar algum tempo para se tornarem visíveis em leituras subsequentes.
- Um
INSERTgrande é enviado paratabledata.insertAllem batches: no máximo 500 linhas por solicitação, além de ser dividido para que cada solicitação permaneça abaixo do limite de tamanho de 10 MB do BigQuery (uma única linha maior que esse limite é rejeitada com um erro claro). - As operações de gravação não são atômicas, e uma única solicitação
tabledata.insertAllpode ser parcialmente bem-sucedida: o BigQuery pode confirmar algumas linhas de uma solicitação e rejeitar outras cominsertErrors. As solicitações também são confirmadas de forma independente, portanto, um lote posterior pode ser rejeitado depois que lotes anteriores forem aceitos. Em ambos os casos, a consulta relata um erro, mas as linhas já confirmadas permanecem no BigQuery. Para limitar duplicações, cada linha é enviada com uminsertIdestável, derivado do ID da consulta e da posição ordinal da linha no stream, que o BigQuery usa para desduplicação de melhor esforço dentro da janela de inserção por streaming. Umquery_idque exceda o limite de 128 caracteres doinsertIddo BigQuery é submetido a hash para gerar um prefixo de comprimento fixo, que permanece estável para essequery_id. Como oinsertIddepende da posição ordinal, a desduplicação só é confiável quando a reexecução produz as linhas na mesma ordem: uma nova tentativa de um lote no nível de transporte é sempre segura, e reexecutar o mesmoINSERTcom o mesmoquery_idsó desduplica se as linhas forem apresentadas na mesma ordem (por exemplo, uma inserção de thread única ou uma ordenação determinística — definamax_threads = 1emax_insert_threads = 1para umINSERT ... SELECTparalelo cuja ordem dos fragmentos poderia mudar entre tentativas).