Construindo Um Pipeline de Dados com Google Cloud Platform

Carolina Dias
12 min readOct 12, 2021

--

Dados e nuvem, uma ótima combinação. Foto de Balázs Utasi no Pexels.

O Porquê 📑

Recentemente participei de um hackathon de engenharia de dados da A3Data. Nele, minha equipe formada por mim e pela Rafaella Duarte, fizemos uma solução toda baseada no ecossistema do Google.

Tivemos até logo pra equipe :D

Mas antes de tudo, qual era o problema? ⁉️

Tínhamos a missão de construir uma pipeline completa de extração, transformação e carga da base de dados abertos de CNPJs do Governo Federal. O uso de ferramentas era de livre escolha dos participantes. Parece algo bem direto, certo? Mas infelizmente o download dos arquivos através do site oficial é extremamente lento e grande, trazendo diversos problemas na hora de fazer sua extração.

Para mitigar esse problema, resolvemos colocar tudo em nuvem, para evitar gargalos nas máquinas locais. Além disso, como os dados são atualizados apenas mensalmente, podemos reduzir o custo de operações em cloud ao atualizarmos o pipeline apenas uma vez por mês.

Enquanto procurávamos sobre alguma solução de pipeline de dados em nuvem, vimos que o material existente é relativamente pouco, principalmente para iniciantes. Então espero que esse material ajude futuras pessoas que venham procurar sobre o mesmo tema.

Mas aqui já vale um disclaimer: existem soluções melhores, mais rápidas e mais eficientes que essa, essa solução foi pensada e colocada pra rodar em menos de uma semana por pessoas que nunca tiveram contato com serviços em cloud antes, então tenha isso em mente durante o texto.

Mas por quê a Google Cloud e não a AWS ou a Azure? 🤔

Duas coisas pesaram muito nessa decisão: facilidade de uso e redução de custos. A GCP é bem intuitiva de se usar e todo o seu ambiente e ferramentas integradas a tornaram uma forte candidata. Além disso, 300 dólares em créditos para novos usuários fizeram com que a escolha ficasse ainda mais fácil, pois não queríamos ter que gastar muito com o serviço. 💸

Acabamos utilizando os seguintes serviços da GCP:

  • 🖥 Compute Engine, como máquina virtual para a execução dos scripts;
  • 🗄 Cloud Storage, para armazenamento dos dados;
  • 🗃 Google BigQuery, para as análises dos dados.

Além disso, utilizamos o 📊 Google Data Studio para fazermos dashboards para as perguntas do hackhaton. Ao final, ficarmos com a seguinte arquitetura da pipeline de dados: na Compute Engine rodamos os scripts que armazenam os dados em storage e os organiza em tabelas no BigQuery, para que possamos fazer dashboards no Data Studio para o usuário final.

Arquitetura da Pipeline de Dados

Breve Introdução à Google Cloud ☁️

Antes de tudo, vamos dar uma pincelada sobre o que é a GCP e mostrar um pouco do seu uso e de suas funcionalidades, para ninguém ficar perdido nos próximos passos.

A Google Cloud Platform (GCP) é, como já vimos, o ecossistema de computação em nuvem do Google. Existem os mais diversos produtos na GCP, desde armazenamento até soluções complexas de Inteligência Artificial.

Para se inscrever na Google Cloud, basta acessar o site e iniciar o cadastro. É necessário um cartão de crédito, mas ele não será utilizado sem permissão, nem mesmo quando os créditos gratuitos acabarem, os projetos simplesmente serão parados caso isso aconteça.

Com a conta criada, vamos então criar um novo projeto no console da GCP, clicando em “Criar Projeto” e dando um nome a ele:

Criação de Novo Projeto na GCP

Ao clicarmos em “criar” seremos redirecionados para a dashboard do projeto, e nela encontramos as mais variadas informações, desde custos até detalhes de cada serviço sendo utilizado.

Dashboard do Projeto que, por enquanto, está vazia

Vamos então começar com os serviços (ou produtos) em si. Ao clicarmos no menu de navegação (ao lado do nome da Google Cloud Platform) abrimos os diversos e muitos produtos que existem, separados convenientemente por categorias. Para facilitar a navegação, podemos pinar os produtos que usaremos, para que apareçam sempre no topo.

Aqui no nosso caso, vamos ter uma breve overview da Compute Engine, da Cloud Storage e do BigQuery.

Produtos que usaremos e que pinamos para fácil acesso

Compute Engine 🖥

Resumidamente, aqui temos o produto de máquina virtual da GCP. Ao clicarmos em Compute Engine precisaremos ativar a API do serviço. E isso vale para todos os produtos que formos utilizar. Ao fazermos essa ativação, vamos então em “Criar Instância” para inicializarmos uma nova máquina virtual. Aqui podemos escolher o nome, o tipo de máquina, a quantidade de memória RAM, de armazenamento e qual sistema operacional nossa máquina terá, além de inúmeras outras configurações mais avançadas e específicas para cada caso.

Página de Configurações de Inicialização de uma Instância na Compute Engine

Pronto, com a instância criada, basta clicarmos em SSH para termos acesso ao terminal da VM pelo próprio navegador, ou seguir esses passos para acessá-lo localmente.

Cloud Storage 🗄

Aqui é onde armazenamos os dados e arquivos em si na cloud. Para isso, criamos um bucket, que é onde ficarão organizados os arquivos. Na criação do bucket, por ora, basta nos preocuparmos com o nome que daremos a ele, e deixarmos todas as outras informações como padrão. Também é possível termos informações de gastos estimados se soubermos aproximadamente de quanto armazenamento iremos precisar.

Página de criação de um novo bucket. Por enquanto nos preocuparemos apenas com o nome.

E pronto, o bucket já está pronto para ser usado para armazenar os arquivos e os dados.

Google BigQuery 🗃

Podemos dizer que este produto bem conhecido da GCP é o nosso banco de dados. Nele podemos criar tabelas e nelas realizarmos consultas em SQL que podem ser exportadas para outros serviços, como o de criação de dashboards do Google Data Studio. Aqui não há muito segredo, criamos um conjunto de dados e nele criamos as tabelas em si. É possível preenchê-las de diversas maneiras, inclusive através de arquivos .CSVs armazenados em um bucket automaticamente. Mas aqui no nosso caso realizaremos esse processo com um script em Python.

Exemplo de uma tabela em BigQuery

Hora de Começar 🕓

A primeira coisa que precisávamos fazer era o download dos arquivos dos dados dos CNPJs no site do Governo Federal. Parecia uma tarefa fácil, até vermos que o site tem velocidades de download baixíssimas, levando horas para baixar apenas um arquivo (e eram mais de 30 deles). Já começava aí a nossa preocupação. 😰

Mas seguimos em frente e pensamos em fazer um script em Python que faz todo o scrapping da página em busca dos links de download. A vantagem é que isso funciona com um ou com mil arquivos, ao invés de termos que colocar os links hard-coded no script.

Para isso, foi utilizada a biblioteca BeautifulSoup para encontrar todos os links (algo bem direto pois todos eles possuem a mesma classe HTML de “external-link”) e armazená-los em uma lista. Após isso, percorremos a lista e fizemos o download dos arquivos que originalmente estão em .ZIP, e a cada arquivo baixado, extraímos o .ZIP para .CSV e deletamos o arquivo .ZIP de origem. Todo esse código pode ser encontrado no arquivo abaixo (omitido do texto por questões de tamanho).

Aqui ficamos nos perguntando se deveríamos fazer o tratamento dos dados já em um script Python, utilizando bibliotecas como Pandas ou Dask, ou se armazenávamos os arquivos .CSV originais em cloud. Optamos pela segunda opção, e um dos motivos foi pelo fato dos arquivos serem muito grandes, o que ocuparia valores muito altos de memória ao tratá-los direto em Python.

A parte de enviar os arquivos pra nuvem com um script foi, inicialmente, um pouco assustadora, pois nunca tínhamos usado nenhum serviço em cloud. Mas após encontrarmos toda a documentação da própria GCP, tudo ficou mais simples. Existem exemplos de scripts em diversas linguagens de programação, e tudo bem documentado. Isso foi de grande ajuda para o projeto. Na parte de autenticação do script com as credenciais da nossa conta, bastou apenas setarmos as variáveis de ambiente na nossa máquina local. Esse passo nem é necessário ao rodá-lo na própria VM do Google.

Enfim, todo esse script de download dos dados, extração do .ZIP para .CSV, exclusão do .ZIP e envio do .CSV bruto para o armazenamento em nuvem foi rodado na máquina virtual da Google Cloud, a Compute Engine. Utilizamos as seguintes configurações para a nossa instância:

  • Sistema Operacional Ubuntu 20.04, por ser fácil de utilizar e por ser um software open source;
  • 4 GB de RAM: inicialmente ficamos em dúvida se precisávamos de um valor tão alto de RAM para rodar apenas um script, mas veremos a seguir que ele veio bem a calhar;
  • 20 GB de armazenamento: colocamos um valor extra aqui para termos mais folga caso algo arquivo seja maior que o esperado, e também porque mais armazenamento era uma opção bem barata. Após o uso, chegamos a conclusão que 10 GB ou menos já seriam suficientes, pois o maior arquivo era aproximadamente de 2 GB quando descompactado.

Com tudo isso em mente, ligamos a VM, conectamos ao GitHub onde estavam armazenados os script que fizemos localmente e os clonamos. Após isso e após a instalação das bibliotecas, rodamos o script de download dos arquivos. Usamos o comando “nohup” no terminal para que os scripts rodassem em segundo plano e podermos fechar o terminal sem encerrar o processo. Extremamente necessário para download nessa (baixa) velocidade.

Ufa! 😌 Parecia que tudo estava funcionando como o esperado mesmo! Mas mesmo assim ainda persistiu o problema de baixa velocidade de download do site dos dados. Se deixássemos eles baixando em série, demorariam dias para terminar. Não tínhamos esse tempo.

Como solução, fizemos uma breve alteração no script original para que baixasse apenas um arquivo por vez e o rodamos diversas vezes ao mesmo tempo na VM, com um script em bash, para baixar todos os arquivos em paralelo. E essa solução meio “manual" acabou funcionando bem, e aí que entrou a necessidade de 4 GBs de RAM na máquina virtual, pois todo esse processo levou a RAM a picos de uso em 3,8 GBs.

Com certeza existem métodos infinitamente melhores de baixar arquivos em paralelo, mas já estávamos correndo contra o tempo para nos focarmos no resto da solução.

Finalmente, depois de tudo isso e de 7 horas rodando, tínhamos todos os arquivos descompactados na storage da GCP. E sim, o download é tão lento pelo site, que mesmo baixando todos os arquivos paralelamente ainda demorou 7 horas.

A velocidade de download dos arquivos

Qual o próximo passo? 🏃🏼‍♀️

Agora que tínhamos os .CSVs dos arquivos brutos na Cloud Storage, precisávamos fornecê-los de alguma forma estruturada para realizarmos as consultas. E foi aí que partimos para o BigQuery.

Como já era de se esperar, todo o processo de transferência de arquivos para o BigQuery é bem documentado e direto de se fazer em script.

Criamos os esquemas das tabelas, com os tipos de dados e seus respectivos nomes a serem percorridos pelo script em Python e a populamos com os dados em .CSV. Eram mais de 30 arquivos, mas eles formaram poucas tabelas, pois os arquivos eram a divisão por partes dos dados. No baseamos no esquema abaixo dos dados originais.

Representação da Base de Dados

Esse processo também foi rodado na máquina virtual, acontecendo de forma bem rápida, inclusive. Tivemos a sorte de esses dados dos CNPJs estarem relativamente limpos e bem formatados. Estava tudo indo bem, até que os problemas resolvem aparecer. Na tabela “estabelecimentos” sempre dava erro na hora de povoá-la no BigQuery. E o erro já é algo bem relatado na documentação da GCP:

Note: By default, if the CSV file contains the ASCII 0 (NULL) character, you can't load the data into BigQuery. If you want to allow ASCII 0 and/or other ASCII Control characters, please contact BigQuery customer support.

Ou seja, haviam caracteres proibidos no .CSV original que impossibilitavam os dados de serem carregados. Depois de várias tentativas para resolver esse problema, encontramos uma solução simples, fácil e rápida: converter, através do terminal, os caracteres problemáticos em caracteres saudáveis. Utilizamos o seguinte comando pra isso:

LC_CTYPE=C tr -d ‘\000’ < arquivo_problematico.csv > arquivo_saudavel.csv

Nesse comando, é essencial o uso do parâmetro LC_CTYPE=C no comando tr (translate) para o funcionamento da conversão dos dados (demoramos bastante pra saber disso).

Com os arquivos problemáticos já corrigidos, conseguimos enfim enviar todos para o BigQuery. Estava tudo pronto para realizarmos as consultas e no prazo esperado :D

Para facilitar na hora de realizarmos as queries (pra não precisarmos fazer 30 joins por consulta) resolvemos fazer uma nova tabela, com uma grande view dos dados que seriam mais relevantes na hora de responder as perguntas pedidas, e foi dessa nova tabela que enfim realizamos as 6 queries finais, uma para cada questão.

Exemplo dos dados presentes na tabela criada apenas com os dados mais relevantes. Detalhe para as mais de 40 milhões de linhas presentes.

Esse processo foi o que menos deu problema (ufa!), creio que a parte mais difícil foi entender as nuances das coisas pedidas nas questões. Mas isso fazia parte do desafio também.

Ao finalizar essas queries finais, salvamos cada uma em uma nova tabela para que os dados ficassem facilmente disponível e acessíveis para a criação das dashboards.

Finalizando… ✅

Agora já está tudo pronto para fazermos os gráficos e finalizar os resultados. Inicialmente tínhamos pensado em utilizar o Streamlit, uma biblioteca em Python que auxilia no deploy de soluções. Mas acabamos por optar pelo Google Data Studio, novamente pela facilidade e alta integração com os serviços da GCP, além de ser gratuito.

Depois de alguns longos minutos (ou horas) de trials and erros, conseguimos os gráficos para cada questão, com os filtros e informações necessárias.

Abaixo, vemos as perguntas pedidas:

  1. Número de indústrias ativas por mês/ano entre 2010–2021, discriminado por MEI ou Simples, em cada município brasileiro.

Precisamos selecionar os dados por mês, por ano, por tipo de estabelecimento e por municípios, pegando apenas as indústrias ativa. Ficamos com:

Dashboard para a questão 01

2. Número de comércios que fecharam por mês/ano entre 2010–2021, discriminado por MEI ou Simples, em cada município brasileiro.

Precisamos selecionar os dados por mês, por ano, por tipo de estabelecimento e por município, pegando apenas os comércios não-ativos. Ficamos com:

Dashboard para a questão 02

3. Número de CNPJ novos por mês/ano entre 2010–2021, discriminado por MEI ou Simples, em cada município brasileiro.

Query análoga à da primeira questão, apenas trocada para CNPJs novos. Obtemos:

Dashboard para a questão 03

4. Qual o número de CNPJ que surgiram do grupo de educação superior, entre 2015 e 2021, discriminado por ano, em cada estado brasileiro?

Aqui podemos separar os CNPJs que tem a educação superior como atividade econômica principal ou como atividade econômica secundária. Optamos por considerar os dois casos.

Dashboard para a questão 04

5. Qual a classe de CNAE com o maior capital social médio no Brasil no último ano?

Agrupamos os dados por classe de CNAE e realizamos a média do capital social. Optamos por mostrar, na visualização, os 10 maiores, ao invés de apenas o primeiro.

Dashboard para a questão 05

6. Qual a média do capital social das empresas de pequeno porte por natureza jurídica no último ano?

Selecionamos apenas as empresas de pequeno porte e tiramos a médio do capital social de todas elas no último ano, agrupadas por natureza jurídica.

Dashboard para a questão 06

Após finalizarmos os dashboards, faltou apenas gravarmos os vídeos pedidos com a solução.

E com tudo isso feito em uma semana terminamos e enviamos nossa solução que foi uma das vencedoras do hackathon 😄

🟣 Dúvidas, dicas ou sugestões são sempre bem-vindas no Linkedin ou Github.

--

--

Carolina Dias

A machine learning engineer learning how machines learn and a mathematician bad at math