Pular para conteúdo

Ingestão e Catalogação de Dados no BigQuery

No projeto InfoEscola, a "ingestão" de dados no BigQuery seguiu uma estratégia arquitetural otimizada e não tradicional: em vez de realizar uma carga física de cópia dos dados para o armazenamento interno do BigQuery (o que geraria custos de armazenamento duplicado), optou-se por catalogar a Camada Bronze existente no Google Cloud Storage (GCS).

🛠️ Técnicas e Arquitetura Utilizadas

A arquitetura escolhida transformou o BigQuery em um motor de consulta sobre um Data Lakehouse, utilizando as seguintes técnicas:

  • Tabelas Externas (External Tables): O processo consistiu em criar "ponteiros" no BigQuery que leem os dados brutos diretamente do GCS. Essa abordagem é serverless, não destrutiva (os dados de origem ficam intocados e imutáveis) e altamente eficiente em custos, pois paga-se apenas pela leitura da consulta e não pelo armazenamento em duplicidade.
  • Adoção do Formato Parquet: Diferente da extração para arquivos TSV.GZ que exige mapeamento manual, o formato Parquet foi utilizado porque armazena o próprio esquema (nomes e tipos das colunas) internamente. Isso permitiu que o BigQuery descobrisse a estrutura dos dados de forma 100% automática ao ler a instrução format = 'PARQUET'.
  • Automação via Script Python: Em vez de registrar centenas de tabelas manualmente pela interface, foi desenvolvido um script Python (02_register_bronze_to_catalog.py) utilizando a biblioteca google-cloud-bigquery. O script acessa o bucket do GCS, descobre automaticamente as pastas e executa as instruções DDL (CREATE OR REPLACE EXTERNAL TABLE) no BigQuery de forma dinâmica.
  • Auto-descoberta de Particionamento (Hive-style): Para estruturar otimizações futuras de leitura, o script utilizou o parâmetro hive_partitioning_mode = 'AUTO'. Isso instrui o BigQuery a analisar a estrutura de subpastas do GCS (ex: .../ano=2025/mes=10/) e inferir essas pastas como colunas virtuais para viabilizar a "poda de partições" (partition pruning) nas consultas.

🚧 Problemas Enfrentados e 💡 Soluções Aplicadas

Durante o desenvolvimento do catálogo no BigQuery, vários desafios técnicos precisaram ser superados:

Problema 1: Trabalho Manual Massivo com TSV vs. Auto-descoberta * O Problema: Inicialmente, algumas extrações de migração utilizavam arquivos TSV.GZ contendo dados brutos convertidos em Hexadecimal para prevenir corrupção. O problema é que, para o BigQuery ler arquivos TSV, era necessário definir o esquema (schema) de todas as centenas de tabelas manualmente no comando DDL, além de configurar delimitadores muito específicos (\x1F). * A Solução: O pipeline abandonou o registro dos TSVs da migração em prol dos arquivos Parquet nativos. Com o Parquet, o script não precisava conhecer o esquema previamente; o BigQuery o absorveu automaticamente de dentro dos próprios arquivos.

Problema 2: Erro de Nomenclatura (Invalid table ID) * O Problema: Durante a execução automatizada, a API do BigQuery retornou falhas como Invalid table ID "fonte=cloud_sql_historico". * A Causa: O script de automação estava lendo a estrutura do bucket GCS de forma genérica e tentou usar uma pasta de marcação estrutural (fonte=cloud_sql_historico) como se fosse o nome lógico da tabela, quebrando regras de sintaxe que proíbem o caractere = no nome. * A Solução: A lógica de descoberta (discover_tables_from_gcs) foi refatorada. Ela foi instruída a ignorar diretórios-pai e pular o nível de pasta do prefixo (tables_gcs_prefix), capturando apenas os nomes de pastas subsequentes (ex: Acao, Contato) para gerar identificadores limpos e mapeá-los para Datasets padronizados (ex: bronze_corp.Acao).

Problema 3: URIs Malformadas com Barras Duplas * O Problema: Em testes de simulação (dry-run), os logs registraram caminhos de URI inválidos sendo enviados ao BigQuery, com barras duplas: gs://infoescola-datalake/bronze/fonte=cloud_sql_historico//TipoCabine/*.parquet. * A Causa: Variáveis de configuração no arquivo settings.py já terminavam com barras, e o script concatenava uma nova barra adicional em tempo de execução. * A Solução: Foi injetada a instrução de sanitização .rstrip('/') nas variáveis antes de montar as strings. A formatação do caminho foi centralizada e finalizada com o wildcard exato (/*.parquet), assegurando que o BigQuery recebesse um URI perfeitamente limpo.

Problema 4: Localização Geográfica dos Dados (Data Residency) * O Problema: Caso os Datasets virtuais no BigQuery fossem criados de forma puramente automática sem parâmetros de localização, eles poderiam ser gerados numa região de nuvem incorreta (ex: EUA), gerando atrito para ler arquivos que estivessem salvos num bucket sul-americano. * A Solução: O script foi ajustado para tratar exceções NotFound. Se o Dataset não existir, o script não apenas o cria, mas injeta explicitamente o atributo da região (dataset.location = "southamerica-east1" ou "US"), garantindo conformidade geográfica entre os metadados do BigQuery e o armazenamento físico do GCS.

🎯 Resumo da Fase

A "ingestão" no BigQuery consolidou-se em uma etapa ágil e moderna de mapeamento de Data Lake. Essa estratégia provou que é possível construir um motor de consulta massivo sobre dados brutos em poucos minutos, delegando ao formato Parquet a responsabilidade pelos tipos de dados e ao Python a automação total, mantendo a camada Bronze descentralizada e imutável.