Base de Dados para Treinamento

Para escrever o Pentaho na Prática eu construí, do zero, uma base de dados – a Beltrano S/A. Ela está disponível na forma de um backup Postgres, com licença que permite até mesmo o uso comercial. Ou seja, se você quiser montar um curso, ou um produto, embutindo a Beltrano S/A, pode.


A única coisa que eu peço em troca é ser informado no que ela está sendo usada. Só. E mesmo assim, se não quiser não precisa me falar nada. Liberdade total. ;-)


A julgar pelo feedback de quem pediu para usar, eu diria que, como material de ensino, a base é interessante. Por outro lado, como tecnologia ela é bem pouco prática, na minha opinião.

Começa que, para usar, é preciso instalar o Postgres. Depois, precisa criar um banco, baixar o backup, restaurá-lo etc. Daí, se você alterar o conteúdo e quiser resetar o banco para o estado inicial, é preciso dropar a base e recriá-la. E se quiser customizar, precisa extrair umbackup no final e repetir o passo-a-passo de configuração em todas as máquinas de alunos.

É um trabalho chato mesmo para quem sabe mexer no Postgres. Para quem tem pouca familiaridade, é um porre.

Nem todo mundo é fluente em Postgres, e nem sempre dá para instalá-lo nas máquinas. Ou até dá, mas pode rolar conflito de porta, restrições de administração, blá blá blá… Eu ministrei umas vinte turmas de [BI com Pentaho][bicp4lin_bitly], e em todas elas sempre houve ao menos uma pessoa/máquina com problema sério na preparação do banco.

Bom, Bonito e Barato

Existe um servidor de banco de dados chamado HSQLDB que é 100% Java e que não precisa ser instalado. Basta baixar o arquivo do programa, rodá-lo com Java e voilà, tudo em riba!

Como se não bastasse ser Software Livre e 100% Java (ou seja, 100% portável – roda em qualquer plataforma, mesmo!), ainda tem uma interface gráfica a lá pgAdmin III, que pode ser usada para explorar os bancos e executar comandos SQL.

Mas tem uma coisa mais legal ainda: os bancos são construídos, por default, em memória. Quando o servidor é baixado, ele grava tudo que estava em memória em arquivos texto planos, no diretório que especificarmos. Isso, mais o fato de tomar muitas de suas configurações de servidor da linha de comando, nos dá muitas vantagens:

  • Qualquer modificação que é feita nos dados pode ser mantida e transferida para outras máquinas, simplificando o processo de customização para cada uso;
  • Se quiser voltar ao estado original, basta apagar o banco atual e descompactar o banco inicial mais uma vez. Estou falando do Beltrano S/A, mas pode ser feito para qualquer outro banco que você criar: basta guardar uma cópia à parte do seu banco;
  • Ele não mantém arquivos escondidos. Apagou, desinstalou;
  • A porta é configurada na chamada que sobe o servidor. Deu conflito? Baixe o banco, mude a porta e suba novamente;
  • Como podemos rodar um programa Java quantas vezes quisermos, podemos montar um conjunto de vários servidores, cada qual com sua porta e seu banco;
  • Um mesmo servidor, aliás, pode manter vários bancos;
  • É um programa pequeno: o pacote inteiro não chega a 5MB;
  • Mesmo tendo uma “pegada” muito pequena, ele não deixa nada a dever a bancos maiores, em termos de funcionalidades, e aguenta um bom volume de dados (basicamente limitado pela RAM da máquina;)
  • Você pode embuti-lo em outros programas, afinal é um projeto livre, em Java;
  • Você pode carregar data marts nele, e dar a capacidade de processamento de dados in memory a qualquer ferramentas de análises de dados que se conecte a bancos de dados via JDBC, como o Pentaho. Evidentemente não é a mesma coisa que um engine otimizado, como o que acompanha o QlikView, mas é mais rápido que disco.

E o HSQLDB ainda oferece uma boa gama de comandos e recursos, como índices, integridade relacional, muitos tipos de dados, várias funções nativas etc. etc. etc. Não fica a dever para outros bancos, mesmo.

Quem me conhece deve estar esperando a pegadinha, que sempre vem depois que eu desenho uma cena linda, toda rósea e luminosa. ;-) Bom, desta vez não tem: é tudo róseo e lindo, mesmo! No restante do post você verá um pouco sobre o HSQLDB (como baixar e subir um banco) e como instalar o mesmo conteúdo do banco Beltrano S/A oferecido em PostgreSQL.

Introdução ao HSQLDB

Como a promessa deste post é oferecer uma base de treinamento pronta e fácil de usar, eu vou cortar direto para a perseguição1 e ensinar o bê-a-bá do agá-esse-kê-ele-debê: de onde fazer o download, como subir o servidor, criar novos bancos, acessá-lo e depois baixá-lo.

O site do HSQLDB é o http://hsqldb.org, onde você pode estudar toda documentação e ler os guias de uso. Como é um projeto voltado principalmente para programadores (é um banco embutível, afinal de contas), ele abusa da linguagem técnica, tanto SQL quanto Java, e pode ser um pouco árido para o usuário menos proficiente nesses assuntos.

O pacote do servidor HSQLDB pode ser baixado diretamente do SourceForge, neste link, e o pacote do Beltrano S/A pré-configurado pode ser baixado daqui. O restante desta seção usa o conteúdo desse pacote, não do servidor original – muito técnico, lembram-se?

O zip do Beltrano OLTP/HSQLDB traz os arquivos do servidor e mais dois scripts, cada um dos quais em duas versões: Linux (.sh) e Windows (.bat.) Um dos scripts sobe o servidor e outro baixa-o. Os diretórios são ./data, onde fica o conteúdo do banco propriamente dito, e ./lib, onde está o servidor.

Subindo e Baixando o HSQLDB

Basta rodar o script start-hsqldb.sh/bat que o HSQLDB subirá com o banco desejado – Beltrano S/A neste caso. Para rodar esse script, abra um terminal (Windows: prompt do DOS) e mude para o diretório recém-criado. Daí comande ./start-hsqldb.sh (Linux) ou start-hsqldb.bat (Windows.) Em poucos segundos o banco estará no ar.

Eis as mensagens do HSQLDB subindo em um Ubuntu:

ubuntu:beltrano_oltp_hsqldb$ ./beltrano_oltp_hsqldb
classpath is :./lib/hsqldb.jar
[Server@5cd73256]: [Thread[main,5,main]]: checkRunning(false) entered
[Server@5cd73256]: [Thread[main,5,main]]: checkRunning(false) exited
[Server@5cd73256]: Startup sequence initiated from main() method
[Server@5cd73256]: Could not load properties from file
[Server@5cd73256]: Using cli/default properties only
[Server@5cd73256]: Initiating startup sequence...
[Server@5cd73256]: Server socket opened successfully in 4 ms.
[Server@5cd73256]: Database [index=0, id=0, db=file:./data/beltrano10k, alias=beltrano_oltp] opened successfully in 1430 ms.
[Server@5cd73256]: Startup sequence completed in 1435 ms.
[Server@5cd73256]: 2016-11-24 10:37:47.379 HSQLDB server 2.3.4 is online on port 9001
[Server@5cd73256]: To close normally, connect and execute SHUTDOWN SQL
[Server@5cd73256]: From command line, use [Ctrl]+[C] to abort abruptly

Eis o conteúdo da versão Bash do script:

#!/bin/sh
### =================== ###
##  HSQLDB Start Script  ##
### =================== ###

DIR_REL=`dirname $0`
cd $DIR_REL
DIR=`pwd`
cd -

#---------------------------------#
# dynamically build the classpath #
#---------------------------------#
THE_CLASSPATH=
for i in `ls $DIR_REL/lib/hsqldb*.jar`
do
THE_CLASSPATH=${THE_CLASSPATH}:${i}
done
echo "classpath is $THE_CLASSPATH"

java -cp $THE_CLASSPATH org.hsqldb.Server
-database.0 $DIR_REL/data/beltrano
-dbname.0 beltrano_oltp -port 9001

O último comando do script acima deve estar em uma única linha.

Uma vez no ar, você não pode simplesmente apertar CTRL+C para interrompê-lo. Isso pode corromper os arquivos, sem contar que não vai salvar o que estiver em memória. Para encerrar um banco é preciso rodar o script stop-hsqldb.sh/.bat. Note que talvez seja preciso abrir outro terminal. O script de encerramento é o seguinte:

#!/bin/sh
### =================== ###
##  HSQLDB Stop Script  ##
### =================== ###

DIR_REL=`dirname $0`
cd $DIR_REL

java -jar $DIR_REL/lib/sqltool.jar
--inlineRc=url=jdbc:hsqldb:hsql://localhost:9001/nome_do_banco,user=SA,password=""
--sql="SHUTDOWN;"

De novo: linhas maiores foram separadas em várias para facilitar a leitura, mas sempre devem formar uma única linha, sem quebras.

A diferença deste script para o de inicialização é que você não precisa informar o(s) nome(s) do(s) banco(s): ao receber o comando para se desligar, o HSQLDB encerra todos que estiverem abertos. Apenas não se esqueça de conferir as portas: o comando de shutdown precisa ser enviado para a porta certa, caso contrário, óbvio, nada acontecerá.

Acessando o Servidor

O HSQLDB é um servidor de banco de dados como outro qualquer. Ele pode ser acessado por qualquer aplicação que use o padrão JDBC. O driver JDBC dele, aliás, é o próprio servidor. No pacote do Beltrano S/A o servidor/driver é o arquivo hsqldb.jar, que fica dentro da pasta ./lib. Basta passar esse arquivo para o programa que vai se conectar ao servidor HSQLDB e usar a string de conexão abaixo:

jdbc:hsqldb:hsql://:/; ~~~

`<PARAMETROS>` é qualquer configuração que precise ser passada para o servidor. Lembre-se de remover o **;** entre a URL e os parâmetros caso não haja nenhum.

Digamos que você queira usar o PDI (Kettle) para acessar esse servidor. Uma conexão com o HSQLDB é totalmente padrão: basta selecionar Hypersonic (seu antigo nome) na lista e entrar os dados de conexão:

<a href="https://geekbi.wordpress.com/wp-content/uploads/2016/11/161123_basededadosparatreinamento_004.png"><img class="size-full wp-image-1550" src="https://geekbi.wordpress.com/wp-content/uploads/2016/11/161123_basededadosparatreinamento_004.png" alt="Parâmetros de conexão Pentaho." width="608" height="500" /></a> Parâmetros de conexão Pentaho.

Porém, é importante setar um parâmetro para evitar problemas com &quot;conjuntos vazios&quot; (conexões que se abre e fecham sem gravar nada, acho.) Na janela de conexões do *Spoon*, acesse a seção *Options* e entre o parâmetro `allow_empty_batch = true`:

<a href="https://geekbi.wordpress.com/wp-content/uploads/2016/11/161123_basededadosparatreinamento_003.png"><img class="size-large wp-image-1551" src="https://geekbi.wordpress.com/wp-content/uploads/2016/11/161123_basededadosparatreinamento_003.png?w=720" alt="Onde adicionar o parâmetro para evitar problemas com INSERTs vazios." width="720" height="278" /></a> Onde adicionar o parâmetro para evitar problemas com INSERTs vazios.

A string de conexão ficaria:

jdbc:hsqldb:hsql://localhost:9001/beltrano_oltp;allow_empty_batch=true

<br />Aproveitando, se você precisa construir uma conexão [JNDI][JNDI_bitly], o formato é esse:

BELTRANO_OLTP/type=javax.sql.DataSource
BELTRANO_OLTP/driver=org.hsqldb.jdbcDriver
BELTRANO_OLTP/url=jdbc:hsqldb:hsql://localhost:9001/beltrano_oltp
BELTRANO_OLTP/user=sa
BELTRANO_OLTP/password=

<br />Lembre-se de ajustar os parâmetros para o seu caso!

### Criar Novos Bancos ###

Pronto, agora você possui um servidor de banco de dados portátil, versátil, apto a um monte de usos educacionais e profissionais. Por exemplo, você pode criar um Data Mart para servir relatórios.

> ---
>
> Francamente, eu não consegui entender a documentação. Não sei dizer se dá para criar um banco subindo um servidor "vazio" e fazendo um `CREATE DB` ou coisa do gênero. Logo, eu vou contar aqui o que eu sei que funciona, mas não é necessariamente a única forma de fazê-lo - eu só não sei de outras. ;-)
>
> ---

Observe a linha de comando Java do script de inicialização:

java -cp $THE_CLASSPATH org.hsqldb.Server
-database.0 $DIR_REL/data/beltrano
-dbname.0 beltrano_oltp -port 9001

<br />É ali que definimos que bancos o servidor vai oferecer, a partir de que diretório, em que porta etc. Logo, para criar um novo banco basta adicionar, a essa linha, um par de parâmetros:

* Diretório do banco e nome dos arquivos: `$DIR_REL/data/NOME`
* Número e nome do banco de dados: `-dbname.X NOME`

Você pode adicionar um novo banco ou remover o antigo antes de criar o novo, apagando os arquivos `$DIR_REL/data/NOME`.

Para subir mais de um banco no mesmo servidor, inclua um novo conjunto de parâmetros. Por exemplo, para termos dois bancos, chamados *nome_do_banco* e *banco_de_dados*, a linha de comando deve ser:

java -cp $THE_CLASSPATH org.hsqldb.Server
-database.0 $DIR_REL/data/nomequalquer1 -dbname.0 nome_do_banco
-database.1 $DIR_REL/data/nomequalquer2 -dbname.1 banco_de_dados
-port 9001

<br />> *Atenção*: o comando acima deve compor uma única linha.

E, claro que você já deve ter sacado, para alterar a porta na qual o banco vai responder simplesmente mude o número que vem depois do parâmetro `-port`.

### Interface Gráfica ###

Em 17/1/2013 eu postei um artigo mostrando como abrir uma interface gráfica ("mais ou menos") para um servidor HSQLDB: [Interface para o HSQLDB][inthsqldb_bitly]. Vamos relembrar os pontos importantes:

* Abra um terminal (DOS prompt no Windows)
* Mude para o diretório do *HSQLDB*;
* Comande:
java -cp hsqldb.jar org.hsqldb.util.DatabaseManagerSwing --noexit

* Preencha os campos da janela Connect com os seguintes dados:

Setting name: Beltrano OLTP
URL: jdbc:hsqldb:hsql://localhost:9001/beltrano_oltp
User: sa
Senha:
~~~

A figura abaixo mostra um exemplo. Note que ela se conecta a outro banco, e por isso os parâmetros são diferentes – ela foi puxada do outro post.

Exemplo de como criar uma nova conexão.
Exemplo de como criar uma nova conexão.

Quando você conseguir se conectar, poderá explorar o banco à vontade:

Conectado ao servidor.
Conectado ao servidor.

HSQLDB & Pentaho

Se você costuma usar o Pentaho, especialmente o servidor, vale a pena notar que esse é o banco que o Pentaho BA Server usa em sua instalação pré-configurada. Se você tiver curiosidade, tudo que foi descrito aqui pode ser verificado no diretório ./biserver-ce/data, se você souber a quê estou me referindo.

Conclusão

Eu já havia visto MySQL portátil, que é uma boa solução também. O único inconveniente era o fato de precisar de binários diferentes para cada arquitetura (Linux, Windows, Intel, ARM etc.) O HSQLDB supera essa limitação e é, de fato, um servidor de bancos de dados relacionais de arquitetura “universal”. Claro que não possui a mesma robustez de um servidor como Oracle ou PostgreSQL, mas resolve muito bem uma série de necessidades.

Não sei porque eu demorei tanto a perceber isso… ;-)

Não deixe de entrar em contato por meios dos comentários se tiver alguma dúvida, ou encontrar algum bug.

Até a próxima! :-)


  1. Cut to the chase é uma coisa que dizem em Inglês quando não estão a fim de ouvir a história inteira. Aqui usamos mais “vá direto ao assunto”. E porque eu usei a expressão estrangeira? Oras, para poder dizer que GeekBI é cultura, claro! Kkkk…. 

Exame & BigData

A revista exame publicou, em 5 de março deste ano (2016), um artigo comentando sobre o mercado de trabalho para “Cientistas de Dados”.

Eu sempre implico com nomes “da moda” porque, na minha opinião, eles desvalorizam o profissional sedimentado, experiente, abandonando expressões que funcionam por um palavreado mais colorido. Ocasionalmente a coisa muda, claro, e esses nomes precisam mudar junto, mas em TI há uma competição disfarçada para ver quem vem com a próxima buzzword. No final essa disputa acaba por atrapalhar a vida da TI porque tanta mudança forçada impede a construção de senso comum e de uma cultura particular.

Pergunte a um engenheiro mecânico o que é um carburador, ou se eles usam “camâras adiabáticas para oxiredução explosiva”. Ou para um financista se ele fala juros compostos, ou “taxa de interesse recursiva”.

Entendeu a idéia? Para quê mudar uma expressão se ela adequa-se perfeitamente?

Pior: uma pessoa errada, mas com muita certeza, vai levar outros a errar também. É preciso estar de posse de um conhecimento sólido para poder resistir à pressão do hype corrente.

Big Data, Hiper Hype

Nestas últimas semanas eu tenho escrito sobre BigData, mas ontem eu não tinha assunto. Eu não sabia sobre o que postar, e depois de um dia cheio e tela em branco, eu simplesmente desisti.

Sem inspiração? Que tal tocado como gado?
Sem inspiração? Que tal tocado como gado?

Hoje eu acordei e olhei de novo para minhas anotações e achei este rascunho aqui, sobre a Revista Exame, e vi um bom fechamento para a série. Junte-se a isso que eu repeti minha palestra sobre BigData para a Fatec Zona Sul, cujo foco era desfazer confusões antes de começarem.

Leia a reportagem, é interessante. Entretanto, lá no meio, quando tudo estava indo bem, algo dá errado:


“O big data não se resume a um processo de automação. Seu objetivo é entender melhor o que acontece numa empresa, o que os clientes querem e, assim, modificar o negócio”, diz Jorge Sanz, diretor do Centro de Business Analytics da Universidade Nacional de Singapura, um dos grandes centros de big data da Ásia. Esse processo requer softwares capazes de captar os dados relevantes — e, acima de tudo, pessoas treinadas para interpretá-los.


Eu copiei o parágrafo inteiro como está. Releia. Releu? Entendeu? De novo, devagar:

“O big data não se resume a um processo de automação.”

“O” big data? Agora é uma coisa só, um objeto que anda por aí, e não mais uma tecnologia, mas um objeto. Ok, vamos dar uma colher de chá, já que muitos profissionais ainda chamam BI de “O” BI.

“Não se resume a um processo”: então “big data” é um processo? Se ele diz “não se resume”, então ele já classificou o assunto como um processo; apenas vai adiante e diz que não é apenas um processo – mas implica que é um de qualquer forma. Ou seja, passou de tecnologia-objeto (que demanda o tal do artigo definido masculino singular, “O”) para uma coisa que também é um processo. Mais uma confusão, mas vamos relevá-la de novo, em favor da prosa da reportagem.

“De automação”: e de onde veio isso? Do parágrafo anterior no artigo, onde ele começa associando computadores a automação. Até são coisas relacionadas, mas chamar Hadoop de automação é um pouco demais. Mas mesmo assim, vamos em frente.

E aqui o assunto descarrilha de vez:

“Seu objetivo é entender melhor o que acontece numa empresa”

É um repórter competetente, entrevistando um executivo relevante de uma enorme instituição financeira nacional. Quer dizer, não é um par de manés, não! São profissionais experientes, gabaritados e entendidos no assunto…

… que meteram os pés pelas mãos. Há décadas existe um termo que usa como definição justamente essa frase – Seu objetivo é entender melhor o que acontece numa empresa: Inteligência de Negócios, vulgo BI.

O que ele fez foi chamar uma coisa de outra. Foi vender banana anunciando carambola, já ambas são compridas, amarelas, tem casca, são frutas… Só que não são a mesma coisa! É um esforço feito para dar ribalta a uma expressão da moda, dando um gancho (sigam este link, é hilário!) em outra!

Fora, Inteligência de Negócios! Agora queremos "o big data"!
Fora, Inteligência de Negócios! Agora queremos “o big data”!

Existe uma outra explicação, que é dizer que ele não sabia mesmo do que estava falando, mas isso é um pouco demais para aceitarmos. Afinal, é a maior revista de negócios do Brasil, não um panfleto de bairro. Não atribuiriam a um repórter uma tarefa que ele não conseguisse desempenhar adequadamente. Isso feriria a reputação de ambos – revista e repórter. A menos, claro, que seu público não fosse capaz de perceber a confusão, mas aí é demais para aceitarmos porque estamos falando de um público qualificado, líderes, executivos e profissionais de todos os ramos, conhecedores de assuntos mil…

Entenderam como funciona? Ninguém tem bem certeza do que é algo. Aí a moda vem, avassaladoramente, e sacode tudo junto. No final fica parecendo aquela piada:


O bêbado entra no ônibus, passa a roleta e vai para trás. De lá, grita:

  • Do lado direito todo mundo é palmeirense! Do lado esquerdo todo mundo é corintiano!

Ao ouvir isto, levanta um do lado direito e fala:

  • Eu não sou palmeirense!!!

E todo os passageiros começaram a xingar o bêbado e ameaçando cobri-lo de bolacha. O motorista, para evitar confusão, freia bruscamente e todos caem. Um dos passageiros se levanta, pega o bêbado pelo colarinho e pergunta:

  • Fala de novo, safado! Quem é palmeirense e quem é corintiano?!

  • Agora eu não sei mais. Misturou tudo…


Não dá mais para saber quem é quem, porque o jornalismo especializado misturou tudo.

Conclusão

A reportagem segue nesse mesmo ritmo, dando novos nomes a coisas já estabelecidas. Por exemplo, em certo momento ele diz que os cientistas de dados têm remuneração superior à dos técnicos, que até o surgimento do big data eram os responsáveis por cuidar da manutenção dos bancos de dados. Ele misturou DBAs com analistas de DW/ETL, com Analistas de Data Mining, com Hadoop, com Bancos Relacionais… Em metade de um parágrafo, em menos de 30 palavras, causou-se estrago para pelo menos três áreas:

  • DBAs fazem a mesma coisa que cientistas de dados se você não usar “big data”;
  • Cientistas de Dados são DBAs para “big data”;
  • A manutenção de um Hadoop, uma plataforma de clusterização escrita em Java, é feita por um cientista de dados, enquanto que a de um Oracle, um banco de dados relacional, é feita por um técnico, e são a mesma coisa do ponto de vista funcional;
  • E Data Mining?

Esse tipo de artigo confunde um número de conceitos complexos para uma audiência em geral leiga nestes mesmos tópicos. Por ser um veículo de projeção nacional e respeitado, bem-conceituado, muitos tomam o que sai ali por fato, por verdade canônica. Aos poucos essas confusões tomam o lugar das verdades nas empresas, impactando planejamento, contratações, e até debates. Como é que um cara qualquer, um joão-ninguém como eu pode argumentar com o “repórter da Exame”? A quem acreditam vocês que o público atribui maior conhecimento? :-)

E pior ainda: como é que um profissional recém-formado pode querer colaborar com a empresa, se tudo que ele fala é contestado pelo chefe que viu tudo diferente na revista de negócios mais famosa do Brasil?

Tem mais razão e está mais certo que fala com mais convicção? Não, né? Repasso aqui o conselho que dei àqueles alunos das FATECs:

Use sua inteligência para filtrar. Critique e questione tudo. ;-)
Use sua inteligência para filtrar. Critique e questione tudo. ;-)

É isso. ;-)

A Orquídea, o Pântano e o Jacaré

A Orquídea, o Pântano e o Jacaré

10/08/2016 [Link para o post.][post_bitly]

Mostrei meu post Lago ou Pântano? a um colega de trabalho e ele matou a pau. O comentário dele foi tão interessante que eu resolvi publicá-lo aqui, como uma lição para todos nós.

Mas eu não vou entregar assim de graça, vocês vão ter que ler até lá. ;-)

Data Lake

Você pode ler sobre o conceito direto do pai dele, James Dixon, neste post. Em resumo, DL é uma tecnologia que captura “tudo”, direto para um repositório Hadoop, e que fica disponível para quem quiser usar. Esse paradigma coloca uma série de questões. Por exemplo:

  • Se dados no Hadoop não aceita updates, como lidar com incrementos?
  • Devemos capturar as fontes de dados e seus metadados?
  • Como arquivar as evoluções de layout da origem?
  • Como tratar tempo-real?

E assim por diante. Essas questões, dirão vocês, provavelmente foram resolvidas na cabeça do Dixon, ou então são partes das dores evolutivas de uma nova tecnologia. Não discordo de nenhum destes argumentos. Em TI nada nasce completo, e faz parte do ciclo de vida de cada nova tecnologia se aprimorar e se apurar a cada nova versão.


Estudando para escrever este post eu acabei assistindo este vídeo, que mostra como injetar dados em um Hadoop automaticamente. Preciso admitir que é impressionante. Na verdade, estou morrendo de vontade de testar, mas para um caso de uso muito específico: stage!


O Problema de um Data Lake

Se aqueles detalhes são apenas isso, detalhes técnicos, e não são problemas, quais são os problemas que um Data Lake coloca?

Ora, muito simples. Se ele é mesmo uma réplica de todos os dados de todos os sistemas de uma organização, então ele carrega os mesmos problemas de usar os dados na origem:

  • Sujos;
  • Não-integrados;
  • Não-documentados;
  • Inconstantes.

São exatamente os problemas resolvidos por um projeto de DW, que mira em entregar dados prontos para uso a partir de várias origem. Ou seja, um projeto de DW promete entregar:

  • Dados limpos, prontos para consulta;
  • Integrados;
  • Com uma explicação clara sobre sua função e origem;
  • Imutáveis.

Portanto, ou o projeto de Data Lake incorpora, por definição, um subprojeto de DW, ou o usuário final deve fazer isso tudo sozinho!

Posso ouvi-los cantando meu nome:

“Fábio, Fábio, Fábio, homem de pouca fé! É óbvio que o cliente não está sozinho!”

Não? Então os usuários de Data Lake vão trazer apoio para entender e integrar os dados… De onde? Do sistema de origem, dos próprios DBAs e tals? Bom, se essa é a solução, ok, quem sou eu para desdizer!

Estou zoando, mas a questão é séria. O usuário vai até o DL e, sozinho, escolhe as fontes de dados? Como ele vai saber qual daqueles arquivos contém o dado que ele precisa, ou que é que significa cada uma daquelas colunas e tabelas? E como saber de que forma cada tabela se liga com outras tabelas?

Não tem como se virar sozinho, 100% sozinho, em um curto espaço de tempo. Raramente a informação sobre os dados existe empacotada em algum lugar, à disposição de quem precisar. Geralmente esse conhecimento todo está espalhado em documentos de sistema, na cabeça de DBAs e na cabeça de usuários de cada sistema. Se virar sozinho com o Data Lake implica em gastar muito tempo e, mesmo assim, provavelmente gastaria esse tempo perguntando coisas a quem sabe.

Lembrando que cada novo consumidor deste Data Lake vai repetir os mesmos caminhos. Depois de recuperar os dados, ainda precisa tratá-los de alguma forma – limpando-os e integrando-os – para depois carregar em alguma estrutura que permita a consulta dos dados, o uso destes dados para um propósito qualquer.

É como se trocássemos uma padaria, na qual compramos o que precisamos, por um grande silo que visitamos para comprar o trigo, e depois em casa convertê-lo em pão, macarrão, biscoito etc.


Já pensou que terror??

  • Manhê! Dá um Negresco?

  • Peraí, filhote…

  • Mas mãe, faz duas semanas que você diz “peraí”… Esse biscoito num assa nunca?

  • Assar, até assa, meu filho. E fazer o chocolate para misturar com a farinha para fazer o biscoito, nem foi tão difícil. O diacho é secar o tacho de caldo-de-cana para conseguir o açúcar mascavo para conseguir o açúcar refinado para fazer o recheio com o leite que seu pai trouxe lá da fazenda da Parmalat… E nem pense em pedir bife à parmeggiana de novo!!!

:-D


Até parece Minecraft

Só para constar, o mundo já foi assim. Naquele tempo alguém percebeu que poderia fazer algum dinheiro transformando o trigo em farinha, e outro percebeu que poderia vender macarrão com a farinha do fulano, e assim por diante, até chegarmos neste nosso mundo de Pães de Açúcar, padarias e postos de gasolinha em todas as esquinas.

JÁ PENSOU TER QUE REFINAR PETRÓLEO EM CASA???? :-O

Conclusão

Eis a conversa com meu amigo, regalem-se:

(09:15:36) Fábio: Você entendeu, não?
(09:16:09) Colega/DEPTO: o super-herói precisará entender todas as regras de todas as bases de origem
(09:16:44) Fábio: ISSO!!!!! :-D
(09:17:25) Fábio: É tão bem colocado que eu vou fazer um take dois!
(09:17:26) Colega/DEPTO: vai lá procurar uma orquídea dentro de um pantano!
(09:17:44) Colega/DEPTO: o jacaré vai te comer
(09:17:58) Fábio: quá quá quá!
(09:18:23) Fábio: O nome desse próximo post vai ser A Orquídea, O Pântano e o Jacaré.

Vamos destacar, imprimir e pendurar na parede:


Sobre Data Lakes:

O [usuário] super-herói precisará entender todas as regras de todas as bases de origem. Vai lá procurar uma orquídea dentro de um pântano! O jacaré vai te comer.

Vitor Rosan

Savan Extraordinaire


Falou pouco mas disse tudo! ;-)


10/10/2016 08:10:41Complemento

Cheguei no trabalho, abri meu IM e pulou:


(05-10-2016 17:14:06) Vitor: boa tarde
(05-10-2016 17:14:20) Vitor: está ocorrendo aquilo que você profetizou no seu blog, sobre o datalake
(05-10-2016 17:14:55) Vitor: tem muitas pessoas tentando obter dados da base do dw recorrendo a mim para explicar como achar o caminho no meio do pântano


Reparem que ele comenta sobre a minha “professia” do Data Lake, mas depois fala do DW. Eu não entendi na hora, mas a explicação é simples: ainda nem entrou o Data Lake no ar, nem começou, e o problema de entender os dados já está acontecendo em um DW normal, com gerenciamento insuficiente.

Imagine no Data Lake? :-D

 

Data Vault – Satélites?

No post Data Vault – Como Usar  falei um pouco sobre a motivação, conceitos e arquitetura envolvida em um projeto de DW baseado em Data Vault. Um dos meus leitores colocou algumas perguntas muito interessantes, tão interessantes que eu decidi respondê-las em um post exclusivo. Além de ser um meio mais cômodo que um formulário de comentários, é uma forma de agradecer pela participação e mostrar o quanto eu apreciei. ;-) (Sim, eu sou fã dos meus leitores.)

Perguntas, Perguntas, Perguntas

Eis as perguntas colocadas no comentário:

1) Nos satélites, você cita um campo “Load End Date/Timestamp: data e hora do fim da validade daquele registro (default é NULO);”. Neste ponto eu fiquei em dúvida. O ETL para estes satélites poderão realizar operação de update ou não? Ou este campo seria apenas para os casos de atributos que já tiveram uma “vigência fechada” nos OLTP (estou fazendo analogia ao SCD tipo II)?

2) Eu e um colega discutimos se o DV seriam bancos de dados para cada sistema transacional ou todo o DV corporativo estaria em um único banco de dados. Você sugere o DV deveria estar em bancos diferentes? Ou tudo junto? No meu caso, estou falando de SAS e, consequentemente, datasets são tabelas e diretórios são bancos de dados. Então, na falta de um banco relacional como DV, eu inicialmente colocaria todo o DV num “diretório dvault”.

3) Um BD relacional daria conta de manter um satélite gigantesco (algo como muitos atributos/colunas muitas transações/registros por dia)?

Vou responder uma por seção. Vamos lá.

LEDTS vs. SCD2

O ETL para estes satélites poderão realizar operação de update ou não?

Não apenas podem, como devem. Satélites guardam histórico e possuem exatamente o mesmo comportamento de uma dimensão de variação lenta do tipo 2. Ele acertou na mosca!

Hubs e links são tabelas que guardam os conceitos de negócio da organização, e as relações entre esses conceitos. Se algum dia um determinado hub ou relacionamento entre hubs existiu, o Data Vault captura e arquiva essa informação. Satélites, por outro lado, dão o contexto desses elementos.

O Cofre: Coleção ou Caverna?

A segunda pergunta é mais complexa:

Você sugere o DV deveria estar em bancos diferentes? Ou tudo junto?

Bom, por um simples questão de integração, deveria estar tudo junto.

Buraco Negro

Até que ponto pode crescer um satélite?

Um BD relacional daria conta de manter um satélite gigantesco (algo como muitos atributos/colunas muitas transações/registros por dia)?

Bom, o propósito central de um DV é acumular “todo os dados, para todo o sempre”. Logo, precisamos que a estrutura na qual os dados estão armazenados dê conta disso. Se um relacional não consegue, então precisamos recorrer a algo mais elástico. Inmon chamava essa camada de Near Line Storage, que é um armazenamento de alto volume, mas em uma mídia mais econômica. Em troca pelo preço menor por byte e durabilidade maior, a velocidade de acesso seria menor. No caso original, NLS seriam fitas magnéticas.

Conclusão

A conclusão, desta vez, é minha: do comentário e das perguntas eu posso ver que estou deixando algumas lacunas no assunto de Data Vault. Vou levar essa visão em consideração nos próximos posts sobre o assunto.

Até lá! ;-)

Projeto de Sucesso

Eu já escrevi um pouco sobre como projetos de BI “acontecem”. Em Cruel Sucesso eu divaguei sobre a eterna sensação de fracasso que algubs projetos de BI experimentam, mesmo que ele esteja indo de vento em popa. No Todos os Caminhos Levam a um DW eu me diverti escrevendo uma história maluca sobre um projeto de BI fictício, que nasce como uma planilha Excel e cresce como mandiopã, até explodir e voltar ao começo. Mudando o foco para requisitos, eu discorri sobre Ágil e BI (De Agilidade e BI), para descaradamente anunciar meu curso de requisitos de BI para gestão ágil.

Quase sempre esses posts vem do nada, motivados por alguma situação pela qual passei. Eu estava com o novo fascículo da série Soluções Clássica quase pronto (Credit Scoring), mas aconteceu de novo: me meti num debate sobre o que era um “bom” projeto de BI.

Bom, eu tenho uma idéia do que deve ser um. Vou dividir com vocês a opinião que eu coloquei no debate, mas já sabem, né?


Disclaimer: o que você vai ler é a minha opinião, logo você não é obrigado a gostar dela ou concordar. Terei prazer em ouvir críticas ou outras opiniões, mas no final – como diz o Homer Simpson – a opinião é minha e faço com ela o que quiser, certo?


Sucesso Não Existe

Primeiro, não existe mundo perfeito. Não adianta sonharmos com a próxima grande ferramenta para resolver nossos problemas, porque o melhor que pode acontecer é resolvermos os problemas atuais e caírmos em novos. O que faz a diferença, na minha humilde opinião, é evitarmos empacar. Se empacamos, o projeto começa a fazer água, e quanto mais tempo demoramos para resolver o problema da vez, menos relevante o projeto de BI se torna, até que um dia todo mundo está se virando sozinho e o projeto é mantido vivo apenas com auxílio de aparelhos.

O que torna um projeto bom, de sucesso, então, é o fato de ele estar sempre em movimento, resolvendo cada problema como um corredor salta obstáculos: pula, corre, pula, corre, pula, corre… Eventualmente, um dia a coisa toda entra em velocidade de cruzeiro, a quantidade de erros cai substancialmente e a empresa desenvolve uma cultura de BI. Esse é o projeto de sucesso: falível, sempre precisando de alguma melhoria, mas que entrega resultados e é acreditado pela organização, sustentado pela cultura de conhecimento da empresa.


Um projeto de BI de sucesso, IMHO, é aquele que resolve um problema atrás do outro, sempre entregando um pouco mais de resultados a cada etapa, capaz de suplanta as próprias limitações e ir ao encontro das expectativas do cliente.


O Caminho para o Sucesso

Ora, dirão vocês, bolas. A definição acima é uma rematada platitude: não diz nada de realmente útil ou prático. Concordo. Vamos escrevê-la ao contrário para ver se fica mais claro:


Fracassa o projeto de BI que persistir em trilhar caminhos sem saída.


Consegui me fazer entender? Quando optamos por este ou aquele caminho, corremos o risco de enveredar por uma rua sem saída. Projetos – de qualquer tipo – que reiteradamente optam por entrar em becos sem saída acabam morrendo porque, cedo ou tarde, a organização se cansa de tanto vai-e-vem! Quer seguir no caminho para o sucesso? Esforce-se por evitar decisões ruins!

Decisões, Decisões, Decisões

Devo ter engolido o grilo falante quando era criança, pois eu sempre escuto uma voz fininha, tirando onda com a minha cara. Desta vez ela disse “Intelijumento! Se soubéssemos que decisão vai dar errado, não a tomaríamos! Dã!”

Óbvio, claro, não se questiona isso. É a própria essência do processo decisório, é a meta personificada de se fazer uma escolha: fazer a escolha certa!

Como saber se uma opção, e não a outra, é a correta? Ah, de muitas formas. Em alguns casos estamos passando pelo mesmo problema uma segunda vez. Se da primeira fizemos a escolha certa, tendemos a repeti-la, e vice-versa: deu errado antes? Vamos tentar outra coisa. Em outros casos não conhecemos, ainda, as consequências de cada caminho, mas podemos avaliá-las com o que estivar à mão – opiniões, análises estatísticas, jogar cara-ou-coroa – e escolher a que parece melhor.


Em último caso, recorra a um taxista: eles sempre sabem o que os outros deviam fazer. ;-)


O Que Funciona?

E aqui chegamos no ponto em que eu queria: o que funciona em um projeto de BI? Como montar um projeto que vai empacar menos?

Armazéns de Dados

Um bom DW é fundamental para qualquer projeto de BI de sucesso. Você pode se virar com dumps, ODFs, Data Lakes, mas esses caminhos são becos sem saída: cedo ou tarde o peso da falta de integração dos dados (dumps e Data Lakes) e das manutenções de modelo e ETL (ODFs e EDW Dimensional) vão afundar seu projeto – mesmo que todo o restante funcione.

Logo, lição número um: monte um bom projeto de DW, capaz de incorporar novas fontes num estalar de dedos e de produzir novas apresentações de dados em dois palitos. Quem acompanha meu blog já sabe o que isso significa: Data Vault.

Equipes

Ferramentas são importantes, mas não são nem metade da solução. Problemas são resolvidos por pessoas com conhecimento e competência para aplicar ferramentas, não pelas ferramentas. E outra: muito ajuda quem pouco atrapalha – gerente bom é gerente quietinho, que serve a equipe, ajudando a remover obstáculos.

Processos

Há dois grupos de processos dentro de um projeto de BI, especificamente:

  • Processos de Desenvolvimento;
  • Processos de Atendimento.

O primeiro é batata: é o processo pelo qual a equipe (parte dela, na verdade) mencionada acima produz os resultados requisitados pelo cliente.

O segundo processo é virtualmente ignorado pela comunidade de praticantes de BI: é o processo pelo qual a outra parte da equipe apóia o cliente. Sim! É o time de “vendedores”, instrutores e tutores, que trabalham com o cliente para entender o que ele precisa e transformar isso em requisitos, que serão tratados pelos desenvolvedores; que ajudam cada novo usuário a aprender a usar as ferramentas e os dados do projeto. O tutor é uma figura inexistente na literatura, mas pode ser visto como um instrutor particular, que vai resolver o problema do usuário uma primeira vez, e ajudar o usuário a repetir esses passos. Ele é diferente do instrutor, que ensina a usar o que está pronto. O tutor cria coisas novas – novas práticas, novos usos dos dados, novos requisitos.

Processo de Desenvolvimento

Não tem segredo: waterfall [bigbang][bigbang_bitly] não funciona, ponto final. A única forma de gestão de projetos que dá certo é Ágil, e neste ponto Scrum é o meu preferido.

Processo de Atendimento

De novo, não tem segredo: um grupo de vendedores (ou evangelistas/analistas de requisitos) e apoiadores (instrutores e tutores) expostos exaustivamente, com uma mensagem clara: Precisa de dados? Me ligue!. Eles interagem com o processo de desenvolvimento alimentando novas histórias no backlog (para os vendedores), com o cliente por meio de chamadas de suporte (tutores/suporte técnico) e com a empresa por meio da capacitação corporativa.

Soluções

Todo projeto de BI usa quatro tipos de soluções:

  • Apresentações;
  • Relatórios;
  • OLAP;
  • Data Mining.

As três primeiras são baseadas em ferramentas, e portanto são resolvidas pela incorporação de profissionais das respectivas ferramentas ao time. Já a última é tratada como uma conjunto de projetos-filhos e raramente é tratada in house. O normal, para soluções que envolvem Data Mining, é contratar uma empresa especializada no assunto desejado.


E os painéis? Painel não é solução de BI, é ferramenta de (tcham-tcham-tcham-tcham-tcham!) apresentação de dados (e não, não é ferramenta de análise! Quem analisa é OLAP e Data Mining.) Logo, você pode ler o primeiro item da lista acima como “dashboards“. Porém, há muitas formas de se apresentar dados e eu evitaria fechar esse escopo prematuramente, jogando tudo na vala comum “painel”.


Um bom projeto de BI precisa incorporar essas categorias, sem exceções. Não precisa oferecer tudo ao mesmo tempo, desde o dia 1, mas deve garantir que o roadmap vai contemplá-las ao longo do caminho. Como conseguir isso? Tente incluir no seu time um generalista de BI, aquele cara que entende um pouco de tudo, e sabe como os assuntos se interconectam, como amadurecem ao longo do ciclo de vida do projeto.

Se você não puder contar com um membro permanente, aceite um membro flutuante, como um coacher, por exemplo. Se não existir na empresa, procure um consultor externo. Raramente um profissional desse cresce durante um projeto de BI, e você só vai achar um na sua empresa, à sua disposição, por pura sorte.

Conclusão

Então vamos lá: um bom projeto de BI é composto por um time multi-disciplinar (especialistas em ferramentas de ETL, apresentação e exploração de dados), com uma equipe voltada para o atendimento do cliente (esqueça a idéia de ter “self-service 100%”) e outra voltada para uma linha de produção de soluções. Na entrada dessa linha está um DW baseado em Data Vault, no meio as áreas de dados para consumo e na ponta as ferramentas de uso dos dados (apresentação, relatórios e OLAP.) Pipocando aqui e ali aparecem os sub-projetos de Data Mining, tocados normalmente por consultorias externas e nascendo de necessidades pontuais. Essa visão geral pode ser melhor organizada por um generalista.

Nenhuma destas idéias é minha, e isso em parte me dá confiança nelas: Bill Inmon chama esse modelo de CIF, o inglês para Fábrica de Informações Corporativas.

Diagrama da Fábrica Corporativa de Informações.
Diagrama da Fábrica Corporativa de Informações.

Outro nome para essa abordagem é BICCBusiness Intelligence Competence Center. Veja este artigo para uma discussão mais detalhada do conceito.

Não é um BICC, mas dá uma idéia de como funciona a tal "linha de produção".
Não é um BICC, mas dá uma idéia de como funciona a tal “linha de produção”.

O restante da minha confiança nesse modelo nasce de eu ter experimentado tudo isso: Data Vault, Scrum, Data Mining, OLAP, Relatórios, equipes proficientes etc. etc. etc. Eu vi projetos de BI fracassarem ao descuidar desses fundamentos, como também vi projetos de BI que estão vivos até hoje, alguns zumbis, outros mancando, mas em operação. Se os que dão certo trazem pistas do que pode ser o mais importante, ou o que dá resultados, os que se arrastam, semi-mortos, são os mais valiosos para entender como e porque as coisas dão errado.

É isso, até a próxima. ;-)

As Vantagens do Data Vault

Semana passada, 6/5/16, eu assisti uma palestra sobre uma empresa chamada Attunity, e suas ferramentas para Business Intelligence. Vendo as promessas do representante brasileiro eu me dei conta de que já escrevi bastante sobre DV, mas nunca escrevi especificamente sobre as vantagens trazidas pela adotação de Data Vault. Vamos corrigir isso hoje, partindo desta apresentação.


Você pode pular direto para a lista de vantagens clicando aqui.


Uma Nova Categoria

Estamos em 2016 e já lá se vão cerca de 40-50 anos desde que Bill Inmon começou o debate sobre Armazéns de Dados, e 24 anos desde seu livro Building the Data Warehouse. Muita água passou embaixo da ponte e todas suas idéias estão sedimentadas, firmes, sobre as quais se assenta a moderna indústria de DW. Um destes conceitos é a Corporate Information Factory, que agrupa as fontes de dados e seus consumidores como uma linha de produção.

Diagrama da Fábrica Corporativa de Informações.
Diagrama da Fábrica Corporativa de Informações.

Tal qual a revolução industrial fez com a manufatura, graus de automação sucessivamente maiores estão acelerando e simplificando o desenvolvimento, manutenção e gerenciamento de Data Warehouses. Instrumental para essa revolução foram tecnologias aparentemente irrelevantes, como modelos de dados e metodologias de desenvolvimento.

Metodologias como Scrum, Continuous Integrations e DevOps agem para diminuir a intervenção e variabilidade da ação humana, enquanto que outras, como Modelagem Dimensional e Data Vault, domam a confusão dos sistemas OLTP e permitem a criação de algoritmos. E é justamente essa criação de algoritmos que permite automatizar o processo de desenho, desenvolvimento e manutenção de DWs.

Uma nova categoria de ferramentas brotou desse fértil ambiente: ferramentas de automação de gestão de DW. Ainda não vi esse ramo ser tratado por um acrônimo, nem mesmo ter um nome mais comum, mas acho que, em Inglês, seria algo Data Warehouse Management Solutions, ou DWMS. Já sabem: se virem por aí, apareceu no GeekBI primeiro. ;-)

Continuando, essa categoria já tem alguns nomes internacionais:

Fazia tempo que eu não visitava o BI Ready, empresa de Ian Nicholson com quem já troquei umas idéias no LinkedIn. Surpresa! Ela foi adquirida pela Attunity e agora são um nome só. Não é à toa que, na apresentação, a Attunity declarou pertencer a essa turma – ela comprou “metade” das empresas dessa área!

Esse é o Ian Nicholson, fundador da BI Ready, fazendo a mesma cara que eu faria se tirasse essa foto.
Esse é o Ian Nicholson, fundador da BI Ready, fazendo a mesma cara que eu faria se tirasse essa foto.

Processos e Problemas

Um projeto de DW que hoje é chamado de “tradicional” (i.e., feito com metodologias de mais de 15 anos atrás) envolvia as seguintes etapas:

  1. Levantar os requisitos;
  2. Estudar os dados de origem;
  3. Desenhar o modelo dimensional;
  4. Desenhar o processo de ETL;
  5. Colocar em produção;
  6. Dar manutenção: propagar as mudanças dos sistemas de origem e adequar às novas necessidades do cliente.

Esse projeto em geral era tocado dentro de uma moldura PMI (a.k.a. Waterfall). Era um método tão certeiro e determinístico que até hoje todo mundo sabe que, feito assim, sempre falha.

Os problemas de um DW 'clássico'.
Os problemas de um DW ‘clássico’.

DW feito por cópia dos bancos de origem é a pior escolha possível, a menos que seja para uma padaria, uma farmácia, uma banca de jornais etc. ;-) Veja que não estou falando de palco (stage), mas de montar o DW como uma coleção de réplicas. Um modelo dimensional é o mínimo necessário para sobreviver aos problemas que serão apresentados ao final desta seção.


Com o advento do Manifesto Ágil e Data Vault, um projeto de DW moderno é tocado assim:

  1. Levantar os requisitos da próxima entrega (30 dias;)
  2. Estudar os dados de origem até encontrar o estritamente necessário para próxima entrega;
  3. Desenhar o DV;
  4. Gerar automaticamente o processo de ETL;
  5. Derivar dados para apresentação;
  6. Colocar em produção e reiniciar o ciclo.

A manutenção é incorporada nas sprints.

Veja que, grosso modo, o processo em si não mudou muito: de projeto waterfall passamos para Scrum, de modelo Dimensional no miolo do DW passamos para um Data Vault e o ETL principal é gerado automaticamente.

Os problemas que existem (existiam e vão continuar existindo) são:

  1. Integração: sem integrar e limpar 100% dos dados, todas as respostas são suspeitas. Ou você confiaria nos números sabendo que algo pode ter ficado de fora?
  2. Historiamento: não adianta montar um armazém que não guarda histórico. Fazer isso é cuidar de dados operacionais e jogar a água fora com o bebê – o maior valor dos dados está no histórico;
  3. Mudanças na origem: sistemas transacionais representam os processos que a empresa executa. Se a empresa muda, forçosamente os OLTPs precisam mudar, e o DW vai ter que ser adequado, sempre;
  4. Performance de ETL: a menos que a empresa esteja definhando, ela sempre vai crescer, sempre vai querer mais dados. O hardware para ETL sempre acaba ficando obsoleto, por um motivo ou outro, cedo ou tarde. O truque é extrair tudo que ele pode dar, e não desperdiçar nada;
  5. Velocidade de mudança: por fim, em cima de todos os problemas apresentados, temos o fato de que as coisas não estão ficando mais calmas, mais lentas, e sim mais rápidas, com mais demandas e mais complexidade.

Ferramentas…

As novas ferramentas de automação de DW se propõem a resolver esses problemas.

O Attunity propõe resolver um DW em dois passos:

  1. Usando o Attunity Replicate os dados são trazidos de diversas fontes de dados para um repositório centralizado;
  2. Daí, com o Attunity Compose, um DW é desenhado e carregado automaticamente.

Há um bom grau de magia negra envolvida (=coisas que acontecem sem entendermos claramente como), mas tudo faz um bom sentido. O Replicate se conecta aos bancos de dados de origem e fazem uma engenharia reversa total. Com essas informações ele vai ao banco de destino e recria o banco de origem, respeitando as diferenças de tecnologias. Por exemplo, ele pode replicar bancos MS SQL Server e Oracle para dentro de um único Postgres. Depois ele faz uma transferência inicial, em que replica as origem(ns) inteira(s) no(s) destino(s). A partir do final desta carga, o Attunity Replicate passa a ler o log de commits dos bancos de origem e replicar no destino, em tempo real.

Quem leu meu post Analítico ou Operacional? sabe que essa replicação não é um DW, e que fazer isso “não é BI”.

A Attunity também sabe, e dá o passo final em direção ao DW através do Compose. O que essa ferramenta faz é mais magia negra que a outra:

  1. Através de engenharia reversa e algoritmos especiais, o Compose “descobre” os relacionamentos entre as várias colunas de todas as tabelas das origens;
  2. Usando esse conhecimento, a ferramenta monta um DW – desenha um modelo de dados – automaticamente;
  3. Em seguida constrói (sempre automaticamente) o ETL para esse DW;
  4. Na última etapa ele monta uma área de apresentação de dados, seguindo indicações de que dados o cliente quer explorar.

A ferramenta ainda permite customizações e correções feitas pelo time de DW, de modo que qualquer interpretação incorreta pode ser ajustada.

Ou seja, ele automatizou 100% do processo moderno de desenvolvimento de DWs!!!! E digo mais: !!!!. Mas não pára por aí:

  • Esse DW guarda histórico;
  • A área de apresentação pode expor estrelas multidimensionais, com até mesmo SCDs tipo 2;
  • Ele detecta mudanças nas origens e ajusta o DW e o ETL;
  • Todas essas ferramentas são clusterizáveis, ou seja, podem ser escalonadas horizontalmente.

Isso são coisas que ouvi ou que perguntei durante a apresentação. Há coisas que eu não perguntei, mas presumo que também estejam no pacote, como tratamento de erros de ETL e monitoramentos diversos. Aliás, a parte de monitoramento é muito bacana, também – aprendi um negócio chamado “hot data, cold data”, sobre o qual vou fazer uns experimentos e, eventualmente, vou postar sobre.

… e Soluções

E como o Data Vault se encaixa nesse cenário? Simples: ele oferece tudo que as ferramentas oferecem, sem o custo monetário. Digo monetário explicitamente porque não existe almoço grátis, sempre precisamos pagar por algo. Se não é em dinheiro, vai ser em treinamento e capacitação, por exemplo, ou simplesmente mais trabalho.

DW 'moderno', re-organizado segundo DV.
DW ‘moderno’, re-organizado segundo DV.

Eis a lista de vantagens (ou problemas resolvidos) trazidos pela adoção de Data Vault no miolo do EDW:

  1. Velocidade de desenvolvimento: usar DV corta o tempo necessário para desenvolver e entregar em algumas ordens de grandeza. Por exemplo, coisas que levariam meses saem em dias;
    1. Modelo de dados: o diagrama de dados do Data Vault é construído através de regras simples, que capturam o negócio no modelo. Assim, uma vez que tenhamos a lista de esquemas, tabelas e colunas do sistema de origem, o ato de desenhar um DV é trivial e leva algumas horas, contra algumas semanas de outros formatos;
    2. Processo de ETL: usando o Pentaho Data Integration, o processo de ETL é gerado automaticamente, a partir do modelo elaborado anteriormente. Ainda é preciso juntar as partes (as diversas transformações) dentro de um job (pré-fabricado), mas isso é uma tarefa de minutos. O ETL inteiro sai em menos de um dia;
  2. Integração: o modelo de dados do Data Vault já arquiva os dados de maneira integrada. Ou seja, a integração ocorre via modelo, no momento em que os dados aterrisam no DV;
  3. Historiamento: 100% dos dados de um DV são historiados, automaticamente e por definição;
  4. Mudanças na origem: evidentemente não são tratadas automaticamente – um software pode fazer isso, não uma metodologia. Entretanto, esse impacto é mínimo:
    1. Qualquer mudança na origem não quebra o processo de ETL, ao contrário de DWs baseados em outros modelos;
    2. Mudanças na origem são resolvidas por um algoritmo simples, e qualquer manutenção leva praticamente o mesmo tempo de repetir o desenvolvimento (horas ao invés de semanas, portanto;)
    3. Nenhuma mudança na origem quebra a área de apresentação. A área de apresentação é reformada apenas em casos que afetem-na. Graças a esse fato, o impacto sobre a área de apresentação causada por mudanças nas origens é de mínimo a inexistente;
  5. Performance de ETL: várias vantagens ao usar um DV;
    1. Alta velocidade: por tratar apenas deltas (i.e., as diferenças) por meio de comparações simples, o processo é muito rápido;
    2. Paralelização: graças ao formato do ETL, todas as operações podem ser maciçamente paralelizadas, possibilitanto uso de hardware barato (COTS;)
    3. Resistente a erros: o ETL de um DV é auto-reinicializável por definição, e só é interrompido por falhas graves (hardware ou dados muito corrompidos;)
  6. Velocidade de mudança: é a mesma da velocidade de desenvolvimento – muito rápida.

Como vantagem extra, pelo fato de DV permitir atacar o problema por pedaços, ele se presta à:

  1. Modularização em sprints;
  2. Paralelização do desenvolvimento.

Por ser baseado em processos automatizados e algoritmos, a quantidade de erros é substancialmente menor, gerando projetos de qualidade maior, e mais padronizado.

Conclusão

Já há alguns anos a indústria de BI vem incorporando tecnologias que habilitam novas soluções de problemas complexos, como a construção, gerenciamento e manutenção de Armazéns de Dados. Essas tecnologias surgem como técnicas/metodologias e softwares.

Um software representante desta nova categoria é o Attunity, especificamente os módulos Replicate e Compose. O primeiro copia dados de diversas origens para um mesmo (ou vários) destino(s). O segundo modela um DW e cria o processo de ETL automaticamente a partir da réplica. Não sei com que qualidade, precisão e velovidade o Attunity entrega os resultados, mas a promessa é fantástica, para dizer o mínimo.

Esse produto é resultado de evoluções anteriores. Uma destas é a metodologia Data Vault, que oferece essa lista de vantagens:

  1. Alta velocidade de desenvolvimento: entrega em dia o que levava meses;
  2. Processo de ETL gerado automaticamente – maior velocidade, qualidade e padronização, com menos erros;
  3. Integração: dados são integrados na entrada;
  4. Historiamento: 100% dos dados de um DV são historiados;
  5. Mudanças: resiliente a mudanças na origem, processo de ETL não pára e impacto global (tanto ETL quanto usuários) é de mínimo a irrisório;
  6. ETL de alta performance, imune à erros, restartável e 100% paralelizável (é possível executar simultaneamente todas as etapas da carga do DV;)
  7. Adequado à processos de desenvolvimento ágil;
  8. Desenvolvimento do modelo (dada ferramenta adequada) e do ETL paralelizável.

Com um Data Vault podemos obter os mesmos resultados prometidos pelo Attunity, com menos automação, e com um custo diferente (menor?)

Clicando aqui você vê a lista dos meus posts marcados com Data Vault. Eis links para alguns do meus posts sobre o assunto:

E se você quiser ler sobre o assunto, o livro é este:

Livro sobre Data Vault.
Livro sobre Data Vault.

Só para não deixar vocês pendurados: eu ofereço os dois cursos, Requisitos Ágeis e Data Vault. Fazer essa propaganda dá impressão que eu montei um post para me auto-promover, mas juro que não é o caso deste aqui. Acredito no valor que esses cursos agregam e sentiria que estaria prejudicando você, meu leitor, ao evitar contar que eles existem. Quem me acompanha sabe que quando eu vou vender algo aqui, eu aviso no começo. ;-)


Até a próxima!

Balanced Scorecard & BI

A teoria do Balanced Scorecard por Norton e Kaplan, ou BSC para os íntimos, teve um impacto significativo no mundo do BI. Talvez, aliás, seja essa a raiz da mistura corrente entre OI e BI. Eu estava lá quando isso estava acontecendo, e vou dividir com vocês um pouco das minhas histórias sobre aqueles dias loucos.

O Mundo Até Então

Até meados do ano 2000, o top em BI de usuário era um DSS conhecido pelo acrônimo EIS, de Executive Information System. O EIS era composto por um DW e uma ferramenta OLAP, organizados de tal forma que um executivo poderia enxergar a empresa inteira a partir do topo, da maior agregação, e descer, seguindo o caminho que desejasse, até o nível mais baixo, da linha.

Assim, por definição, todo executivo ganhava o seu centro de controle ou painel de monitoração empresarial. O apelo do sistema é que ele dispensava o usuário de conhecer programação de qualquer tipo, pois um EIS era voltado para o nível gerencial, o nível tático-estrégico da organização.

Ao redor do EIS haviam uma gama de opções, entre produtos e soluções.

Por exemplo, o usuário poderia pedir um gerador de relatórios (um produto), para construir as listagens que bem entendesse, e quando desejasse. Ganhou alguma notoriedade, nesta época, o slogan “entregar o dado certo, no momento certo, para a pessoa certa”.

E haviam as soluções de BI (e ainda hão), que são pacotes fechados com um propósito definido. Soluções como CRM (gerenciamento da interação com cliente), Churn Detection (detecção e prevenção de atrito, como em call centers) ou Credit Scoring (concessão de crédito automatizado), eram desenvolvidas com uso de Data Mining sobre os dados das empresas.

E não esqueçamos dos DWs, projetos sempre complicados e difíceis, e quase sempre operando aos trancos e barrancos. A tecnologia de DWs passou por três momentos de inflexão: a criação de bancos de dados em dispositivos de acesso aleatório, por volta de 1960, foi o primeiro. DASDs habilitaram a existência de Bancos de Dados Relacionais, sem os quais não seria possível construir um serviço viável de exploração de dados – antes usavam-se fitas magnéticas, e qualquer coisa mais complexa que uma listagem agregada era um transtorno. Depois veio o Modelo Dimensional, no início dos anos 90, que resolveu a vida dos usuários ao montar os dados de uma forma inteligível, apta à exploração por analistas de negócios. Ainda faltava resolver o acúmulo de dados, que seguia também aos trancos e barrancos, atendido parcialmente por Modelagem Dimensional. O advento do Data Vault, já na década 2000, resolveu essa parte. Hoje em dia, DWs são problemas só para quem está desatualizado desde 2003.

Enquanto Isso, Na Sala de Monitoramento…

Quando alguém decide que quer gerenciar uma empresa quando crescer, esse alguém faz uma faculdade de Administração de Empresas. Dentro dessa especialidade existe um sem-número de técnicas e teorias voltadas a entender como uma empresa funciona e como tomar decisões para que ela cresca.

Dentro de Administração de Empresas existem subconjuntos de conhecimento que tratam do monitoramento de uma organização, bem como o planejamento estratégico dela. O termo “balanced scorecard” surgido durante a década de 90 refere-se, de maneira geral, a uma técnica de monitoramento de rendimento (performance) que usa indicadores financeiros e não-financeiros. Essa técnica acompanha a execução das atividades por grupos de profissionais e as consequências dessas atividades. Por algumas coincidências, e pelo movimento do mercado, criou-se a percepção que Robert Kaplan e David Norton criaram o conceito, o que não é verdade, pois a técnica já existia antes. Eles apenas desenvolveram um sistema de gerenciamento estratégico que usa a idéia de um balanced scorecard como pino central.

Balanced Scorecard

A premissa de um Balanced Scorecard é que uma empresa pode monitorar a execução de suas estratégias acompanhando certos indicadores-chaves. O Balanced Scorecard do Norton e Kaplan é uma formalização desse conceito em uma metodologia que, automatizada com auxílio da Informática, cristalizou-se em uma solução chamada Strategic Management System (SMS), ou Sistema de Gerenciamento Estratégico.

Essa metodologia está explicada no livro deles, o The Balanced Scorecard: Translating Strategy into Action. Em tese, qualquer um pode implementar o sistema em sua empresa, a partir deste livro. Eu consegui encontrar uma companhia, ESM, que vende tal sistema, aparentemente uma encarnação oficial das teorias da dupla. Eis alguns screenshots dele:

Exemplo de painel ESM.
Exemplo de painel ESM.

 

Exemplo de mapa estratégico ESM.
Exemplo de mapa estratégico ESM.

O grande truque, que deu fama e fortuna aos autores, é saber que parâmetros monitorar e entender como esses parâmetros surgem das métricas geradas pela empresa, como essas métricas se ligam aos objetivos estratégicos.

Exceto por toda essa teoria, um SMS é, nada mais, nada menos que uma coleção de painéis de instrumentos – os famigerados dashboards – com dados coletados dos sistemas da empresa.

So The Story Goes…

O livro deles saiu em 1996, mas eles já vinham fazendo sucesso com essas idéias desde 1992, quando saiu o primeiro paper sobre o tópico.

O mercado por SMS estava aquecido devido ao sucesso da dupla e suas idéias. Implementações desses conceitos começaram a surgir, e a face mais visível desses sitemas era… o dashboard! Mas não acabava aí, não! Os dados que eram apresentados nesses painéis vinham, em geral, dos sistemas informatizados da empresa.

  • BSC é voltado para administração empresarial;;
  • BI também;
  • BSC usa dados integrados;
  • DW, uma subseção de BI, integra dados da organização;
  • BSC apresenta dados em visualizações bacanas;
  • BI também.
  • Etc.

Entenderam o caminho que a coisa tomou? Até parece que BSC e BI estão ligados intimamente, mas o fato é que nem de longe BSC é uma solução de BI!

  • BSC foca em dados correntes e suas relações determinadas a priori, em monitorar os dados da empresa para aquilatar o consistência do planejamento estratégico e sua execução. Os dados são atualizados muito frequentemente (um dia ou menos) e, em boa parte das vezes, apenas a variação dos indicadores é acompanhada, não dos dados mais granulares. O histórico dos dados em si não é capturado, e portanto não é usado;
  • BI é voltado para acumular dados históricos e analisá-los para descobrir suas relações a posteriori, em busca de entender o negócio. Dizemos que os dados são usados para tentar modelar, matematicamente, o funcionamento da companhia. Fala-se em previsão, em estimativas, em correlações previamente ignordas entre as variáveis etc. etc. etc.

Não são coisas estranhas entre si, pois ambos usam dados gerados em sistemas informatizados (BSC menos, BI mais), mas não são a mesma coisa, ou sequer parentes próximos.

Mesmo assim formou-se, no mercado de BI, a percepção de que BSC faz parte de BI.

Ok, vamos relegar essa parte e focar na questão “empresas vendendo BSC, o pão quente do momento”. Imagine o que aconteceu: empresas de BSC, como a tal da ESM mencionada acima, tinham lá o seu produto, que era uma novidade então.

E as empresas que vendiam BI, tinham o quê para mostrar como sendo BSC? Coleta de dados e apresentação de dados – e a teoria do BSC em um livro! Quando vendedores de BSC mostravam seu produto, a aparência, a parte visual era importante. Quando os fornecedores de BI seguiam essa trilha, o que mais aparecia para os clientes eram… Os dashboards!!

Conclusão

Não posso afirmar, categoricamente, que a tecnologia de painéis de instrumentos foi incorporada ao BI por “culpa” do BSC. Mas eu posso contar para vocês que ao visitar clientes interessados em BSC, eu, gerente de soluções SAS, vendedor de BI, era cobrado para mostrar os painéis da solução SAS para BSC. Era contra esse aspecto que a solução oferecida pelo SAS era comparada.

Eu nunca consegui emplacar uma venda de BSC pelo SAS. O produto de BSC da concorrência (não-BI) era bom o bastante para anular as vantagens do SAS (integração de dados díspares e flexibilidade nos painéis) e conseguir o pedido, mesmo sendo mais caro. Na minha opinião, olhando para trás, eu diria que a concorrência tinha uma implementação formal de BSC, completa e pronta, enquanto que o SAS apenas tentava surfar nessa onda, reempacotando seu produto com outro público-alvo diferente do público regular de BI.

Só que, até então, painéis não eram coisas de BI. Caramba, não tinha nem no catálogo do SAS, que tem tudo!

Por isso, na minha humilde opinião, dashboards entraram para o rol de recursos de BI por contaminação do mercado de SMS, do qual o BSC Norton e Kaplan é um ilustre membro. Dashboards não são melhor ferramenta analítica que um cubo OLAP ou um projeto de Data Mining, mas são excelentes meios para levar informação e oferecer visões completas – para apresentação dos dados.

É isso. Até a próxima. ;-)

Analisando os Logs do PDI – Parte 3

No primeiro post da série vimos como configurar a captura de logs nos processos do PDI, e obter informações básicas sobre os resultados de um processo qualquer.

No segundo post eu mostrei como usar os dados de performance de uma transformação para “caçar” gargalos.

Na terceira e última parte vamos entender como usar as tabelas logging channel para montar um relatório que lista todas as transformações e jobs executados a partir de um job-pai.

Cenário

Eis um exemplo básico de ETL que carrega um Data Warehouse dimensional:

Job principal de refresh do DW Beltrano.
Job principal de refresh do DW Beltrano.

O job acima chama uma transformação que, como o nome diz, define as variáveis do processo, e depois segue chamando os subjobs, cada um com uma tarefa específica: atualizar dimensões, carregar fatos e por fim preencher as tabelas pré-agregadas para OLAP. Por último é chamada outra transformação que coleta informações sobre o estado do DW naquele dia.

Dentro de cada um daqueles subjobs temos uma sequência de transformações, como, por exemplo, a carga das dimensões:

Job de sequenciamento de carga das dimensões.
Job de sequenciamento de carga das dimensões.

E cada uma dessas transformações faz a real movimentação de dados:

Carga da dimensão Cliente.
Carga da dimensão Cliente.

Para sabermos se tudo funcionou precisamos consultar o log de cada uma delas. Como os jobs estão amarrados com avanços condicionais (setas verdes), se der algum problema, o processo inteiro é abortado. Isso dá alguma facilidade de monitoração. Rodando no Spoon, o erro fica aparente:

Problema no processamento das dimensões.
Problema no processamento das dimensões.

Só que em produção não temos Spoon, então precisamos examinar o log:

2016/03/19 10:44:20 - Spoon - Starting job...
2016/03/19 10:44:20 - Refresh DW Beltrano - Start of job execution
2016/03/19 10:44:20 - Refresh DW Beltrano - Starting entry [Seta Variáveis]
2016/03/19 10:44:20 - Seta Variáveis - Loading transformation from XML file [file:///home/beltrano/ETL_Beltrano/t_a_seta_variaveis.ktr]
2016/03/19 10:44:20 - BELTRANO - KTR - Seta Variáveis - Dispatching started for transformation [BELTRANO - KTR - Seta Variáveis]
2016/03/19 10:44:20 - Grava timestamp.0 - Connected to database [beltrano_dw] (commit=1000)
2016/03/19 10:44:20 - Recupera Timestamp do Refresh.0 - Finished processing (I=0, O=0, R=1, W=2, U=0, E=0)
2016/03/19 10:44:20 - Seta variável.0 - Setting environment variables...
2016/03/19 10:44:20 - Seta variável.0 - Set variable REFRESH_TIMESTAMP to value [2016/03/19 10:44:20.724]
2016/03/19 10:44:20 - Seta variável.0 - Finished after 1 rows.
2016/03/19 10:44:20 - Seta variável.0 - Finished processing (I=0, O=0, R=1, W=1, U=0, E=0)
2016/03/19 10:44:20 - Grava timestamp.0 - Finished processing (I=0, O=1, R=1, W=1, U=0, E=0)
2016/03/19 10:44:20 - Refresh DW Beltrano - Starting entry [Carga das Dimensões]
2016/03/19 10:44:20 - Refresh DW Beltrano - Carga das Dimensões - Starting entry [Dimensão Clientes]
2016/03/19 10:44:20 - Dimensão Clientes - Loading transformation from XML file [file:///home/beltrano/ETL_Beltrano/t_d_clientes.ktr]
2016/03/19 10:44:20 - Dimensão Clientes - Dispatching started for transformation [Dimensão Clientes]
2016/03/19 10:44:21 - Lê CNPJs.0 - Finished reading query, closing connection.
2016/03/19 10:44:21 - Lê CNPJs.0 - Finished processing (I=5000, O=0, R=0, W=5000, U=0, E=0)
2016/03/19 10:44:21 - Insere Tipo.0 - Finished processing (I=0, O=0, R=5000, W=5000, U=0, E=0)
2016/03/19 10:44:21 - Formata fluxo PJ.0 - Finished processing (I=0, O=0, R=5000, W=5000, U=0, E=0)
2016/03/19 10:44:21 - Lê CPFs.0 - Finished reading query, closing connection.
2016/03/19 10:44:21 - Lê CPFs.0 - Finished processing (I=50000, O=0, R=0, W=50000, U=0, E=0)
2016/03/19 10:44:21 - Insere Tipo e Cargo.0 - Finished processing (I=0, O=0, R=50000, W=50000, U=0, E=0)
2016/03/19 10:44:21 - Formata fluxo PF.0 - Finished processing (I=0, O=0, R=50000, W=50000, U=0, E=0)
2016/03/19 10:44:21 - Une fluxos.0 - Finished processing (I=0, O=0, R=55000, W=55000, U=0, E=0)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - ERROR (version 5.4.0.0-128, build 1 from 2015-06-03_13-41-59 by buildguy) : Unexpected error
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - ERROR (version 5.4.0.0-128, build 1 from 2015-06-03_13-41-59 by buildguy) : org.pentaho.di.core.exception.KettleDatabaseException: 
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - An error occurred executing SQL: 
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - SELECT count(*) FROM d_clientes WHERE cliente_sk = 0
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - ERROR: relation "d_clientes" does not exist
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -   Position: 22
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - 
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.openQuery(Database.java:1722)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.openQuery(Database.java:1652)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.openQuery(Database.java:1648)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.openQuery(Database.java:1635)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.getOneRow(Database.java:2963)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.trans.steps.dimensionlookup.DimensionLookup.checkDimZero(DimensionLookup.java:1681)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.trans.steps.dimensionlookup.DimensionLookup.processRow(DimensionLookup.java:216)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.trans.step.RunThread.run(RunThread.java:62)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at java.lang.Thread.run(Thread.java:745)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - Caused by: org.postgresql.util.PSQLException: ERROR: relation "d_clientes" does not exist
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -   Position: 22
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:405)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:285)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     at org.pentaho.di.core.database.Database.openQuery(Database.java:1711)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 -     ... 8 more
2016/03/19 10:44:21 - Ordena lista.0 - Finished processing (I=0, O=0, R=55000, W=15882, U=0, E=0)
2016/03/19 10:44:21 - Dimensão Clientes - ERROR (version 5.4.0.0-128, build 1 from 2015-06-03_13-41-59 by buildguy) : Errors detected!
2016/03/19 10:44:21 - Estado.0 - Finished processing (I=28, O=0, R=6154, W=6154, U=0, E=0)
2016/03/19 10:44:21 - Carrega Dimensão Clientes.0 - Finished processing (I=0, O=0, R=1, W=0, U=0, E=1)
2016/03/19 10:44:21 - Dimensão Clientes - Transformation detected one or more steps with errors.
2016/03/19 10:44:21 - Dimensão Clientes - Transformation is killing the other steps!
2016/03/19 10:44:21 - Cidade.0 - Finished processing (I=9715, O=0, R=8553, W=8552, U=0, E=0)
2016/03/19 10:44:21 - Dimensão Clientes - ERROR (version 5.4.0.0-128, build 1 from 2015-06-03_13-41-59 by buildguy) : Errors detected!
2016/03/19 10:44:21 - Refresh DW Beltrano - Carga das Dimensões - Finished job entry [Dimensão Clientes] (result=[false])
2016/03/19 10:44:21 - Refresh DW Beltrano - Finished job entry [Carga das Dimensões] (result=[false])
2016/03/19 10:44:21 - Refresh DW Beltrano - Finished job entry [Seta Variáveis] (result=[false])
2016/03/19 10:44:21 - Refresh DW Beltrano - Job execution finished
2016/03/19 10:44:21 - Spoon - Job has ended.

Lendo o log descobrimos, facilmente, que o problema é a tabela d_clientes, que não foi criada no DW.

“Facilmente”?

Talvez em um processo simples, com poucos passos – e quando o erro aparece logo no começo. Mas achar o erro em um log desses, que pode chegar a vários megabytes, é qualquer coisa, menos “fácil”.

Você pode argumentar que basta fazer uma busca por ERROR. Verdade, mas precisaria fazer a busca no log inteiro, até o fim! E depois outra: onde é que apareceu mesmo esse erro? Examine o log outra vez: depois que achar o erro, você precisa seguir o log para cima, para descobrir em que arquivo (job ou transformação) ele ocorreu, ou para baixo, até encontrar o nome do job/transformação – mas não o nome do arquivo!

Resumindo: dá para fazer, mas é um porre.

Encontrando Nemo. Digo, Erros!

Eu sempre digo que sou um cara prático (preguiçoso é feio, ainda que seja mais franco, hehe) e gosto de usar computadores para fazer qualquer tarefa que possa ser feita por eles.

Uma forma mais fácil de encontrar erros é montar uma consulta como a do primeiro artigo e listar tudo que possuir o campo status igual a stop:

 (SELECT
       id_job,
       'Job' as tipo,
       jobname as nome,
       status,
       to_char(replaydate, 'DD/MM/YY HH24:MI:SS') as replaydate
  FROM job
  WHERE status='stop')
UNION
  (SELECT
       id_batch,
       'Transformação' as tipo,
       transname as nome,
       status,
       to_char(replaydate, 'DD/MM/YY HH24:MI:SS') as replaydate
  FROM transformation
  WHERE status='stop')
ORDER BY replaydate,nome

Resultado:

id tipo nome status replaydate
3 Job Popula Empresa-Case stop 23/02/16 20:48
8 Job Empresa-Case – Popula Tabelas Indepentes stop 23/02/16 20:55
2037 Transformação BELTRANO – KTR – Seta Variáveis stop 19/03/16 10:32
2039 Transformação Dimensão Clientes stop 19/03/16 10:33
2041 Transformação Dimensão Clientes stop 19/03/16 10:35
2043 Transformação Dimensão Clientes stop 19/03/16 10:44

Bem melhor, não? O problema aqui é que ele traz todo mundo. Ainda precisaríamos fazer algum filtro para pegar só o do dia anterior, ou até uma semana para trás, ou algo assim.

Mas podemos fazer melhor.

16.3 Árvore Genea-LOG-ica

Segundo Matt Casters, a tabela de logging channels surgiu como uma forma de amarrar os diversos logs: todas as coisas que são geradas no PDI ganham um ID particular, que é usado sempre que precisam – internamento ou no registro de log – se referir à aquele objeto. (Pelo menos foi o que eu entendi.) Isso é uma evolução em relação ao sistema antigo, que usava um ID sequencial para cada item, o que, convenhamos, é algo um tanto quanto noob.

O sistema de logs do PDI grava os canais de log em um tabela com o seguinte layout:

Coluna Tipo Descrição
id_batch int4 ID do lote
channel_id varchar ID do canal
log_date timestamp Data de registro nesta tabela
logging_object_type varchar Tipo do objeto: job, stransformação, banco de dados etc.
object_name varchar Nome do objeto
object_copy varchar Número da cópia do objeto
repository_directory varchar Caminho do objeto (repositório em banco)
filename varchar Diretório e nome do arquivo que contém este objeto
object_id varchar ID do objeto no repositório (repositório em banco)
object_revision varchar Versão do objeto (só para versão EE)
parent_channel_id varchar ID do canal do objeto-pai, que criou este objeto
root_channel_id varchar ID do canal do objeto-ancestral, que deu origem a todos os outros

O PDI pode salvar jobs e transformações em um sistema de arquivos, como um arquivo XML, ou em um repositório em banco de dados. As colunas da tabela que se referem a atributos válidos apenas para artefatos gravados no repositório em banco de dados recebem nulo quando o job ou transformação é gravado como um arquivo ordinário.


Pelo fato de os IDs serem gerados como um hash, o risco de colisão é próximo de nulo. Tanto é assim que as tabelas para canais de job e transformação tem o mesmo layout, e a Pentaho recomenda usar uma só tabela para registrar os dois.

Eis o conteúdo de algumas destas colunas:

Algumas colunas da tabela logging Channels.
Algumas colunas da tabela logging Channels.

Podemos usar essa tabela para listar todos os jobs e transformações envolvidos em um único processo. Depois, usando as tabelas de log de job e transformação, podemos adicionar o status e ordená-los pela data e hora de inicialização (replaydate.) Podemos montar um relatório com esse resultado. Daí poderemos revisar o processamento do dia e encontrar eventuais falhas muito mais – agora sim! – facilmente.

Vamos fazer isso, então.

Lista de Jobs-Raiz

Um job-raiz, por falta de um termo melhor, é um job que está na raiz de um processamento qualquer, e corresponde à lista de todos os tipos de objeto (coluna logging_object_type) JOB, cujo pai é nulo e que as tem a coluna root_channel_id igual à channel_id. Por exemplo, na figura anterior, o último job do ID_BATCH igual à 1023 é um job-raiz.

A consulta que traz isso é:

SELECT id_batch,
       channel_id,
       log_date,
       object_name
FROM job_logging_channels
WHERE logging_object_type = 'JOB'
      AND parent_channel_id IS NULL
      AND channel_id = root_channel_id

E eis o resultado:

id_batch channel_id log_date object_name
18 f411e0d2-… 2016-02-23 21:45:12.588 Popula Empresa-Case
22 9e142006-… 2016-02-23 22:27:00.323 Popula Tabelas de Pedidos
1023 b604142b-… 2016-03-19 10:27:20.576 Refresh DW Beltrano

Essa lista é o primeiro filtro do relatório: o conteúdo da coluna object_name será apresentado ao usuário como um prompt. E como cada job pode ter sido executado diversas vezes, um segundo prompt vai apresentar a lista de datas em que aquele processo foi executado, para que o usuário escolha que corrida analisar.

A lista de datas de execução é obtida com uma consulta na tabela de log do job, filtrada pelo object_name. Usando o job Popula Empresa-Case como exemplo, a lista de datas vem desta consulta:

SELECT DISTINCT
       channel_id,
       replaydate
FROM job
WHERE jobname = 'Popula Empresa-Case'

Usando essas consultas eu comecei o relatório:

Relatório de linhagem do job, com prompts de job e corrida.
Relatório de linhagem do job, com prompts de job e corrida.

Lista de Descendentes

A forma como a tabela de canais foi bolada permite construir uma consulta recursiva, para recuperar todas as partes de um processo, descendo até o último nível. Essa é a forma correta de consultar essa tabela. Porém, como eu não sei tanto SQL para poder construir uma consulta recursiva, vou apenas ser criativo e fazer de outra forma.

Os descendentes daquele job-raiz tem todos uma coisa em comum: o mesmo job-raiz (duhn.) Logo, podemos selecionar todos os elementos – jobs e transformações – que foram executados no mesmo pacote fazendo outra consutla à tabela de log. Eis como selecionar somente os jobs e transformações disparados pelo job principal:

SELECT channel_id,
       logging_object_type,
       object_name
FROM job_logging_channels
WHERE logging_object_type IN ('JOB','TRANS')
      AND root_channel_id = ${job_raiz}

O resultado, especificamente para o caso do job-raiz 9e142006-fb5d-4b28-8b87-1ff0c706919e, é:

channel_id logging_object_type object_name
d4d5227e-c07b-45d1-a6a9-715310de2e7e TRANS Gera Pedidos
56639da7-cb6d-435f-8d1e-c3a1f99c8687 TRANS Gera Parâmetros para Itens de Pedidos
06af3232-75ea-4b7f-b178-eab915e190df TRANS Seta Variáveis de Subitens
ee44ed8d-dbcc-431b-9b9d-d8220fe78838 TRANS Gera Pedidos Detalhes
aa0a4992-be94-4f8e-b0bf-98d14c0baaef JOB Popula Itens de Pedidos
957dc288-16e1-462c-9f1a-89efb026a2a2 TRANS Seta Variáveis de Subitens
4f2927bf-14c5-4b5a-a0d3-8a4c8eb597d7 TRANS Gera Pedidos Detalhes
a4dbea3e-6731-4fc3-92fb-1230888847d9 TRANS Seta Variáveis de Subitens
095dd255-20ec-4b96-a1d5-cf3a316f248d TRANS Gera Pedidos Detalhes
9e142006-fb5d-4b28-8b87-1ff0c706919e JOB Popula Tabelas de Pedidos

Pronto! Temos a nossa lista de jobs e transformações que compõe o job principal! Agora precisamos apenas dos detalhes de cada um deles, que estão nas respectivas tabelas de log de job e de transformação.

Detalhando a Lista

Como os detalhes de jobs e transformações estão em tabelas separadas, vamos fazer dois JOINs e depois reuni-los. Primeiro, os detalhes dos jobs:

SELECT logging_object_type,
       object_name,
       status,
       replaydate
FROM job_logging_channels, job
WHERE logging_object_type = 'JOB'
      AND job_logging_channels.channel_id = job.channel_id
      AND root_channel_id = ${job_raiz}

E agora os das transformações:

SELECT logging_object_type,
       object_name,
       status,
       replaydate
FROM job_logging_channels, transformation
WHERE logging_object_type = 'TRANS'
      AND job_logging_channels.channel_id = transformation.channel_id
      AND root_channel_id = ${job_raiz}

Unindo as duas consultas, temos o resultado completo:

Relatório completo, mostrando a linhagem de execução, ordenada por data/hora.
Relatório completo, mostrando a linhagem de execução, ordenada por data/hora.

Conclusão & Encerramento

O Pentaho Data Integration é uma das mais modernas e sofisticadas ferramentas de integração de dados disponíveis. Entre seus vários recursos estão a captura de logs muito detalhados, dos quais podemos extrair um gama de informaçôes sobre os processos executados por ele.

Nesta série vimos como configurar e usar o sistema de logs do PDI para obter uma visão simples, ainda que minimamente completa, sobre o que se passou em uma dada corrida (primeiro post).

No segundo post vimos como analisar os logs das transformações para detectar os gargalos, isto é, os pontos que puxam a velocidade da dita transformação para baixo.

Com este terceiro post concluímos a série. Vimos como usar um recurso fundamental do sistema de logs, a tabela de “canais” de log (logging channels), para montar uma listagem que sequencia todos os jobs e transformações executados em um processo (clique aqui para baixar o relatório.)

Esses três artigos formam um exemplo simples e prático para monitorar o processo diário, mas há muito que podemos fazer para melhorar a gestão de um DW. Por exemplo, temos todas as possibilidades de automação de detecção de erros e acionamentos por e-mail.

Até a próxima. ;-)

Analisando os Logs do PDI – Parte 2

No primeiro post da série Logs do PDI vimos como configurar as transformações e jobs do PDI para capturar os logs de processamento e como usá-los para monitorar as execuções. Neste segundo post veremos como usar esses dados para identificar gargalos.

Pias & Transformações

Imagine uma pia, na qual uma torneira despeja água. Se entrar mais água do que a pia consegue escoar, a água vai começar a se acumular. Se nada for feito, o nível de água na pia vai subir, e subir, até transbordar. Há duas formas de se evitar que a água transborde: reduzir a entrada ou aumentar a saída. Em termos mais genéricos, para evitar que a água transborde devemos condicionar a entrada à restrição. A “restrição” é justamente a válvula de escoamento da pia.

A velocidade de uma transformação, medida em linhas por segundo, l/s, está condicionada à restrição existente na transformação: a velocidade de uma transformação será igual à velocidade do seu passo mais lento. Esse passo mais lento é o gargalo.


Se uma transformação possuir passos de ordenação de linhas, agrupamentos etc., que represam linhas, a velocidade média da transformação perde essa relação direta. Ainda vai haver uma relação entre a velocidade da transformação e a velocidade do seu passo mais lento, apenas não será mais 1 para 1. Mas, para manter o didatismo do post, vamos assumir uma transformação perfeitamente esférica e sem atrito, na qual essa condição vale. ;-)


Para aumentar a velocidade de uma transformação, portanto, devemos aumentar a velocidade do fluxo (em l/s) no gargalo. Quando a velocidade no gargalo tiver subido o bastante, algum outro passo vai ser o responsável por restringir a velocidade da transformação, se transformando no novo gargalo. Removemos esse novo gargalo, aumentando a velocidade da transformação, e outro aparecerá, reiniciando o processo. Eventualmente, chegaremos num ponto de rendimento máximo da transformação, no qual uma nova mudança em qualquer passo não vai resultar em aumento de velocidade da transformação.

Simples, não?

Engarrafamento de Linhas

E como descobrimos gargalos em uma transformação?

Usando o Spoon para detectar gargalos: notou um pontilhado em volta de algum passo? É um gargalo!
Usando o Spoon para detectar gargalos: notou um pontilhado em volta de algum passo? É um gargalo!

Se você estiver rodando-a no Spoon, a interface gráfica do PDI, é muito fácil. O PDI detecta o gargalo, definido por ele como “o passo que recebe mais linhas do que é capaz de processar”, e faz com que o Spoon apresente um pontilhado animado em volta de cada passo identificado como gargalo. Esse monitoramento ocorre em tempo real, e causa efeitos curiosos: em certas situações o gargalo parece “pular” entre dois ou mais passos, e em outras vários passos são marcados como gargalos, simultaneamente. A dinâmica que causa isso está fora do escopo deste post, mas não é difícil de entender se você parar para pensar um pouco.

Para que seu Spoon mostre esse passo na sua transformação você precisa habilitar o checkbox Show bottleneck transformation steps, conforme visto na figura abaixo. Essa janela aparece quando selecionamos o item Options, no menu Tools.

Onde fica o checkbox que habilita a exibição do gargalo.
Onde fica o checkbox que habilita a exibição do gargalo.

Essa opção é muito boa durante o processo de desenvolvimento, mas o que fazer para transformações que rodamos em produção? É um ambiente diferente – memória diferente, disco diferente, carga (tarefas simultâneas) diferentes! Se bobear até o sistema operacional é diferente! Não dá para rodar uma por uma no Spoon e ficar olhando, esperando encontrar um passo-gargalo.

Você adivinhou: consultamos o log de performance.

Entendendo o Gargalo

Conforme o próprio PDI coloca, um gargalo (ou restrição) é “um passo que recebe mais linhas do que é capaz de processar”. Para entender isso você precisa saber um pouco sobre a estrutura interna de um passo.

Um passo possui, grosso modo, três partes:

  1. Buffer de entrada: onde são gravadas as linhas que chegam do passo anterior, e onde elas ficam esperando ser processadas;
  2. Motor do passo: retira uma linha do buffer de entrada, processa e grava o resultado no buffer de saída, repetindo esse processo enquanto o passo anterior estiver mandando linhas;
  3. Buffer de entrada: onde são gravadas as linhas processadas pelo passo, e onde elas aguardam até o engine do PDI movê-las para o passo seguinte.
Todo passo possui dois buffers: entrada e saída.
Todo passo possui dois buffers: entrada e saída.

Assim, se o motor do passo, o processamento em si, não for rápido o bastante, ele começa a ficar para trás: as linhas começam a se acumular no buffer de entrada. Se, além disso, se o passo seguinte for no mínimo tão rápido quanto o passo atual, as linhas processadas não “esquentam cadeira” no buffer de saída, e vão sendo levadas adiante. Por exemplo, na transformação simples mostrada abaixo, com três passos, o passo do meio é um gargalo:

O passo do meio é um gargalo: buffer de saída com menos linhas que o de entrada.
O passo do meio é um gargalo: buffer de saída com menos linhas que o de entrada.

Note que os buffers do passo do meio, representados pelas caixas de entrada e saída, aparecem vazio na saída e cheio na entrada. Essa é a condição de gargalo, ou de restrição. Se pudermos aumentar (elevar) a vazão dessa restrição, a velocidade da transformação, como um todo, aumentará.

Como vemos isso nos logs? Bom, quando rodamos uma transformação no Spoon, este monta um quadro de métricas dos passos, e atualiza-o conforme a transformação vai sendo executada, conforme as linhas vão sendo processadas.

Passos e seus parâmetros durante execução.
Passos e seus parâmetros durante execução.

A coluna input/output, última à direita na imagem anterior, exibe a relação entre a quantidade de linhas presentes no buffer de entrada, aguardando processamento, e quantidade de linhas no buffer de saída, aguardando transporte até o passo seguinte. Sempre que um passo possui mais linhas em sua entradas que em sua saída, ele está “segurando” a transformação. Para encontrarmos os gargalos de uma transformação, então, basta analisarmos os passos dela, em busca de buffers de entrada cheios e buffers de saída vazios (ou com bem menos linhas.)

Analisando Vazão em Transformações

O log que captura as métricas de cada passo, segundo a segundo, chama-se Performance. Veja como ativá-lo no primeiro post da série. Essa tabela possui as seguintes colunas:

  • id_batch
  • seq_nr
  • logdate
  • transname
  • stepname
  • step_copy
  • lines_read
  • lines_written
  • lines_updated
  • lines_input
  • lines_output
  • lines_rejected
  • errors
  • input_buffer_rows
  • output_buffer_rows

Reparou nas duas últimas? São as que nos interessam.


Não vou montar uma solução pronta, mas mostrar como usar essa tabela para desenhar algo que atenda à sua necessidade – e depois vou mostrar um exemplo do relatório que eu uso para “debugar” transformações em produção.


Precisamos de uma consulta que traga os buffers, por cada passo, por transformação. Além disso, como cada transformação pode ter sido executada várias vezes, precisamos filtrar também por lote (id_batch.) Essa consulta ficaria assim:

SELECT
  id_batch,
  transname,
  stepname,
  input_buffer_rows,
  output_buffer_rows
FROM transformation_performance
WHERE
  id_batch = X AND
  transname = 'x'

Filtrando para lote 2080 e transformação Carga da Lista de Clientes PF, temos:

id_batch transname stepname input_buffer_rows output_buffer_rows
2080 Carga da Lista de Clientes PF Gera strings aleatórias 224 276
2080 Carga da Lista de Clientes PF Cria CEP, Telefone e Fax 0 0
2080 Carga da Lista de Clientes PF Cria CEP, Telefone e Fax 0 0
2080 Carga da Lista de Clientes PF Lê nomes 0 0
2080 Carga da Lista de Clientes PF Cria as partes de CEP, Telefone e Fax 0 0
2080 Carga da Lista de Clientes PF Muda rnd_telefone/fax para string 0 0
2080 Carga da Lista de Clientes PF Seleciona endereço 2 0
2080 Carga da Lista de Clientes PF Lê sobrenomes 0 61
2080 Carga da Lista de Clientes PF Acerta tamanho das strings 0 0
2080 Carga da Lista de Clientes PF Seleciona sobrenome 61 0
2080 Carga da Lista de Clientes PF Lê lista de enderecos 0 0
2080 Carga da Lista de Clientes PF Seleciona nome 0 0
2080 Carga da Lista de Clientes PF Cria ID do Cliente 1560 225
2080 Carga da Lista de Clientes PF Insere cidade_id 1 3
2080 Carga da Lista de Clientes PF Limpa fluxo 0 0
2080 Carga da Lista de Clientes PF Cria índice do endereço 276 125
2080 Carga da Lista de Clientes PF Gerar linhas 0 2444
2080 Carga da Lista de Clientes PF Cria índices de nome 147 110
2080 Carga da Lista de Clientes PF String operations 3 1
2080 Carga da Lista de Clientes PF Absoluto de rnd_cpf 110 3
2080 Carga da Lista de Clientes PF Grava tabela 0 0
2080 Carga da Lista de Clientes PF Gera strings aleatórias 1778 5755
2080 Carga da Lista de Clientes PF Cria CEP, Telefone e Fax 0 0

E aí, consegue dizer se algum destes passos é um gargalo? Nem eu. Vamos melhorar nossa consulta: vamos agrupar por passo, remover o nome da transformação e lote da execução, já que ambos são previamente conhecidos (estão no filtro.) Fica assim:

SELECT
  stepname,
  sum(input_buffer_rows) as buffer_entrada,
  sum(output_buffer_rows) as buffer_saida
FROM transformation_performance
WHERE
  id_batch = 2080 AND
  transname = 'Carga da Lista de Clientes PF'
GROUP BY
  stepname
ORDER BY
  stepname

Resultado:

stepname buffer_entrada buffer_saida
Absoluto de rnd_cpf 4289 2770
Acerta tamanho das strings 10117 10100
Cria as partes de CEP, Telefone e Fax 100 10098
Cria CEP, Telefone e Fax 10101 20099
Cria ID do Cliente 21021 11892
Cria índice do endereço 15660 3458
Cria índices de nome 3483 4289
Gerar linhas 0 21902
Gera strings aleatórias 11889 15658
Grava tabela 20281 0
Insere cidade_id 202 259
Lê lista de enderecos 0 0
Lê nomes 0 0
Lê sobrenomes 0 61
Limpa fluxo 20099 20281
Muda rnd_telefone/fax para string 125 100
Seleciona endereço 258 714
Seleciona nome 714 100
Seleciona sobrenome 161 125
String operations 2770 202

Já dá para dizer se alguém é gargalo? Não! Veja, buffer de entrada e buffer de saída são métricas não-aditivas: somá-las ao longo do tempo não dá nenhuma informação sobre o processo. Nem somando-as ao longo dos passos, ou das transformações, nada! No máximo, como métricas não-aditivas, talvez uma média ao longo do tempo possa dar alguma idéia do que está acontecendo.

Mesmo assim, a média não ajudaria. Lembra-se que o monitoramento de gargalo do Spoon ocorre em tempo real? E que os gargalos podem pular de um passo para outro? Só conseguimos identificar um gargalo olhando o comportamento dele ao longo do tempo, momento a momento.

Incluíndo o tempo na consulta, temos:

SELECT
  stepname,
  logdate,
  sum(input_buffer_rows) as buffer_entrada,
  sum(output_buffer_rows) as buffer_saida
FROM transformation_performance
WHERE
  id_batch = 2080 AND
  transname = 'Carga da Lista de Clientes PF'
GROUP BY
  stepname,
  logdate
ORDER BY
  stepname

Vai nos dar a seguinte saída:

stepname logdate buffer_entrada buffer_saida
Absoluto de rnd_cpf 2016-02-21 16:34:41 110 3
Absoluto de rnd_cpf 2016-02-21 16:34:41 110 3
Absoluto de rnd_cpf 2016-02-21 16:34:42 87 100
Absoluto de rnd_cpf 2016-02-21 16:34:43 4092 2667
Absoluto de rnd_cpf 2016-02-21 16:34:44 0 0
Absoluto de rnd_cpf 2016-02-21 16:34:45 0 0
Absoluto de rnd_cpf 2016-02-21 16:34:46 0 0
Absoluto de rnd_cpf 2016-02-21 16:34:46 0 0
Acerta tamanho das strings 2016-02-21 16:34:41 0 0
Acerta tamanho das strings 2016-02-21 16:34:42 0 0
Acerta tamanho das strings 2016-02-21 16:34:43 120 100
Acerta tamanho das strings 2016-02-21 16:34:44 9997 10000
Acerta tamanho das strings 2016-02-21 16:34:45 0 0
Acerta tamanho das strings 2016-02-21 16:34:46 0 0
Acerta tamanho das strings 2016-02-21 16:34:46 0 0
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:41 0 0
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:42 0 0
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:43 100 101
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:44 0 9997
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:45 0 0
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:46 0 0
Cria as partes de CEP, Telefone e Fax 2016-02-21 16:34:46 0 0
Cria CEP, Telefone e Fax 2016-02-21 16:34:41 0 0
Cria CEP, Telefone e Fax 2016-02-21 16:34:42 0 0
Cria CEP, Telefone e Fax 2016-02-21 16:34:43 101 100
Cria CEP, Telefone e Fax 2016-02-21 16:34:44 10000 10000
Cria CEP, Telefone e Fax 2016-02-21 16:34:45 0 9999
Cria CEP, Telefone e Fax 2016-02-21 16:34:46 0 0

Agora podemos dizer, se em algum instante, um passo se comportou como um gargalo. Claro que examinar os dados assim é uma bobagem – podemos montar um gráfico com isso.

Relatório de Análise de Fluxos

Juntando essa consulta com os relatórios do primeiro post, montamos um relatório de análise de fluxo de transformações:

Relatório de análise de fluxo em transformações.
Relatório de análise de fluxo em transformações.

Esse relatório traça a velocidade daquele passo em linhas por segundo no gráfico de cima, e o volume de linhas presentes nos buffers, no gráfico de baixo, tudo instante a instante. O que vemos é que esse passo possui uma vazão boa, até, de 20.000 l/s, e que ele nunca esteve em condição de gargalo. Muito pelo contrário: no instante 5 ele teve o seu buffer de saída completamente cheio, sugerindo que o passo seguinte poderia ser um gargalo.

Eis o trecho da transformação que estamos analisando:

Trecho final da transformação de carga de clientes PF da Beltrano S/A.
Trecho final da transformação de carga de clientes PF da Beltrano S/A.

Os passos seguintes são um Select Values e um Table Output. Eis os buffers do Select Values:

Buffers do Select Values.
Buffers do Select Values.

E os do Table Output:

Buffers do Table Output.
Buffers do Table Output.

A-há! Veja ali, do momento 3 ao momento 6, como o buffer de entrada (a linha vermelha) sobe até atingir 10.000 linhas, enquanto o buffer de saída permanece em zero! Esse passo é um gargalo! Ele ficou com o buffer de entrada cheio, que fez com que as linhas “transbordassem” para o passo anterior, o Select Values. Tanto esse Select Values não é um gargalo que os dois buffers sobem e descem juntos. Mais ainda: foi justamente entre os momentos 3 e 6 (comuns a todos os passos, aliás, pois o log de performance captura todo mundo junto) que o buffer de saída do passo Cria CEP, Telefone e Fax saturou, isto é, atingiu seu limite de 10.000 linhas, e começou a se refletir no buffer de entrada, mesmo que por apenas um segundo (cada momento equivale a um segundo nesta escala.)

Conclusão

A partir da consulta mostrada podemos criar um relatório que exibe o estado dos buffers de cada passo momento a momento. Usando a transformação como guia, podemos analisar cada um dos passos em busca do sintoma de restrição de fluxo.

Essa não é a melhor análise, já que nos obriga a olhar um por um. Como você faria essa análise automaticamente? Como deixar para o Report Designer detectar os gargalos de uma transformação?

E apenas para fechar o problema encontrado neste exemplo: um gargalo em um passo que grava dados no banco significa que a rede e o banco é que são os gargalos. Dependendo da influência da rede e do banco na força da restrição, podemos levar o processamento para mais perto (reduzindo o custo da rede) ou melhorar o banco com, por exemplo, discos mais rápidos.

Na próxima semana terminaremos a série com um relatório de genealogia de um processo de ETL.

Até lá!


Novo Lançamento!

Sexta-feira, 11 de março de 2016, será o lançamento do meu novo livro, Autopublicação na Prática. Não deixe de passar por aqui, porque – como sempre – ele será lançado por R$ 0,00!

Analisando os Logs do PDI – Parte 1

O Pentaho Data Integration, antigamente conhecido por Kettle, é a ferramenta de integração de dados da Suite Pentaho. É, de longe, a ferramenta de maior sucesso deles e tanto é assim que fornecedores tradicionais desse mercado “sentiram o calor” da concorrência.

Neste post eu não vou falar sobre o PDI em si, mas sobre uma de seus recursos: o log.

Toco Cru

Em inglês, log significa “tora de madeira”.

Those are the logs.
Those are the logs.

Ou diário, como em captain’s log, o diário do capitão, ou lab log, que é aquele caderninho preto em que cientistas anotam o que aconteceu nos experimentos. :-) Quando dizemos que um programa gera logs, estamos querendo dizer que ele registra, em algum lugar, informações sobre o que está acontecendo. Podem ser erros, avisos ou simplesmente uma narração das ações do programa. Em geral, cada entrada no registro possui uma etiqueta de tempo, ou timestamp, para que seja possível saber quando tal evento ocorreu, e colocá-los em sequência, para estudo.

Transformações e jobs do PDI geram uma profusão de dados durante seu processamento, e a maioria dos usuários do PDI vê parte desses dados na saída do processamento:

geekbi@dw:/opt/pentaho/5.1/data-integration$ ./pan.sh -file=/home/Beltrano/00_Beltrano_1.0/ETL/t_d_date.ktr
2016/02/21 10:50:04 - Pan - Start of run.
2016/02/21 10:50:05 - Dimensão Data - Dispatching started for transformation [Dimensão Data]
2016/02/21 10:50:05 - d_date.0 - Connected to database [beltrano_dw] (commit=10000)
2016/02/21 10:50:05 - Days of week.0 - Finished processing (I=0, O=0, R=0, W=7, U=0, E=0)
2016/02/21 10:50:05 - Months.0 - Finished processing (I=0, O=0, R=0, W=12, U=0, E=0)
2016/02/21 10:50:05 - 10000 dias: 25 anos.0 - LineNr : 5000
2016/02/21 10:50:05 - Days_since.0 - linenr 5000
2016/02/21 10:50:05 - 10000 dias: 25 anos.0 - LineNr : 10000
2016/02/21 10:50:05 - 10000 dias: 25 anos.0 - Finished processing (I=0, O=0, R=0, W=10000, U=0, E=0)
2016/02/21 10:50:05 - Days_since.0 - linenr 10000
2016/02/21 10:50:05 - Days_since.0 - Finished processing (I=0, O=0, R=10000, W=10000, U=0, E=0)
2016/02/21 10:50:05 - Calc Date.0 - Linenr 5000
2016/02/21 10:50:05 - DayOfWeekDesc.0 - linenr 5000
2016/02/21 10:50:05 - MonthDesc.0 - linenr 5000
2016/02/21 10:50:05 - Select values.0 - linenr 5000
2016/02/21 10:50:05 - d_date.0 - linenr 5000
2016/02/21 10:50:06 - Calc Date.0 - Linenr 10000
2016/02/21 10:50:06 - Calc Date.0 - Finished processing (I=0, O=0, R=10000, W=10000, U=0, E=0)
2016/02/21 10:50:06 - Quarter.0 - Finished processing (I=0, O=0, R=10000, W=10000, U=0, E=0)
2016/02/21 10:50:06 - DayOfWeekDesc.0 - linenr 10000
2016/02/21 10:50:06 - DayOfWeekDesc.0 - Finished processing (I=0, O=0, R=10007, W=10000, U=0, E=0)
2016/02/21 10:50:06 - MonthDesc.0 - linenr 10000
2016/02/21 10:50:06 - MonthDesc.0 - Finished processing (I=0, O=0, R=10012, W=10000, U=0, E=0)
2016/02/21 10:50:06 - Select values.0 - linenr 10000
2016/02/21 10:50:06 - Select values.0 - Finished processing (I=0, O=0, R=10000, W=10000, U=0, E=0)
2016/02/21 10:50:06 - d_date.0 - linenr 10000
2016/02/21 10:50:06 - d_date.0 - Finished processing (I=0, O=10000, R=10000, W=10000, U=0, E=0)
2016/02/21 10:50:06 - Pan - Finished!
2016/02/21 10:50:06 - Pan - Start=2016/02/21 10:50:04.785, Stop=2016/02/21 10:50:06.757
2016/02/21 10:50:06 - Pan - Processing ended after 1 seconds.
2016/02/21 10:50:06 - Dimensão Data -
2016/02/21 10:50:06 - Dimensão Data - Step Days_since.0 ended successfully, processed 10000 lines. ( 10000 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step Calc Date.0 ended successfully, processed 10000 lines. ( 10000 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step DayOfWeekDesc.0 ended successfully, processed 10007 lines. ( 10007 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step MonthDesc.0 ended successfully, processed 10012 lines. ( 10012 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step Select values.0 ended successfully, processed 10000 lines. ( 10000 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step d_date.0 ended successfully, processed 10000 lines. ( 10000 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step Quarter.0 ended successfully, processed 10000 lines. ( 10000 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step Days of week.0 ended successfully, processed 7 lines. ( 7 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step Months.0 ended successfully, processed 12 lines. ( 12 lines/s)
2016/02/21 10:50:06 - Dimensão Data - Step 10000 dias: 25 anos.0 ended successfully, processed 10000 lines. ( 10000 lines/s)

Essa é só a narração dos eventos, mas muitos outros dados são capturado durante o processamento: quantidade de linhas lidas e gravadas em bancos e arquivos, quantidade de linhas processadas em cada passo, conteúdo de variáveis carregadas, conexões feitas, erros, aviso – o PDI captura tudo, tudo, até a vazão da pia da cozinha. Esses dados podem ser descarregados diretamente num banco, o que habilita o gestor do projeto a monitorar a carga minuciosamente. Por exemplo, podemos criar indicadores de performance e acompanhá-los diariamente, ou buscar informações sobre o que aconteceu durante uma corrida qualquer do ETL.

Está série é composta de três posts. Nesta primeira parte vamos mostrar como configurar o PDI para injetar os dados capturados em um banco de dados e como construir um relatório bem simples, com indicadores básicos sobre o processamento.

Na Parte 2 veremos como descobrir gargalos, que são pontos de lentidão no fluxo de dados. Por fim, na parte 3, veremos um relatório que dá a genealogia (quem chamou quem, a que horas e quanto tempo levou) de um job, uma informação crucial para o monitoramento da “saúde” do processo.

Ativando a Captura de Log

O PDI descarrega seu log apenas em bancos de dados. Por isso você precisa ter um banco de destino para gravar seus logs. Normalmente eu mantenho um esquema de log nos mesmos bancos dos DWs, pois isso simplifica tanto o desenvolvimento quanto a análise.

Uma vez que você tenha um banco/esquema, precisamos definir quais tabelas receberão os logs. De novo, eu adoto um padrão: trans_LOG para log das transformações, e job_LOG para jobs. Neste caso, LOG é o nome do log capturado na tabela.

Na versão 5.4 o PDI captura os seguintes logs (com o nome da tabela que eu uso entre parênteses):

  • Transformações:
    1. Transformation (transformation): registra uma linha por transformação, por corrida. O campo LOG_FIELD contém o log de texto do processamento;
    2. Step (transformation_steps): registra um sumário do processamento de cada passo, em cada transformação, por corrida, em uma linha por passo. Ligado à anterior pela coluna ID_BATCH;
    3. Performance (transformation_performance): mede a vazão de linhas através de cada passo, segundo a segundo, em cada corrida de uma transformação, uma linha por passo, por segundo. Ligado à tabela de log de transformações pela coluna ID_BATCH;
    4. Logging channels (transformation_lc): registra os nomes e propriedades dos “canais” de dados em uma transformação ou job;
    5. Metrics (não coleto esta): http://forums.pentaho.com/showthread.php?137582-Output-steps-metrics-How-to-use
  • Jobs:
    1. Jobs (jobs): equivalente à da transformação, registra os dados de cada execução de um job em uma linha. Assim como na transformação, o mesmo campo LOG_FIELD contém toda saída de texto do processamento;
    2. Job Entry (job_entry):
    3. Job Logginc Channels (job_lc): registra os nomes e propriedades dos “canais” de dados em uma transformação ou job. Possui o mesmo layout que a logging channels das transformações. Pelo que entendi, a “boa prática” é serem a mesma.

Eu simplifiquei um pouco essas descrições, ou a coisa viraria um livro. Por exemplo, cada log possui parâmetros de tempo de vida e latência de atualização. Consultem o Pentaho Infocenter, a Wiki, o Kettle Solutions ou o Pentaho na Prática para mais informações. Nosso foco hoje é aprender a capturar e usar.


Todos esses parâmetros são entrados na aba de log das janelas de propriedades das transformações…

Aba de logs de uma transformação.
Aba de logs de uma transformação.

 

… e jobs:

Aba de logs de um job.
Aba de logs de um job.

Para chamar essa janela clique com o botão direito sobre qualquer parte em branco de um job ou transformação e, no menu que aparecer, escolha Transformation settings (ou Job settings.)

Esses parâmetros podem ser preenchidos de três maneiras:

  1. Manualmente, entrando os nomes de tabelas e valores dos parâmetros um por um, em toda transformação e job que você criar. Essa alternativa é boa para testes e estudos, enquanto você não está em projeto, por que é mais rápida e prática. Só que, se estiver em um projeto e definir todos os valores manualmente, você vai ter um trampo cabuloso para mudar qualquer coisa, pois vai ter que editar todos os artefatos, um por um, do processo inteiro;
  2. Por meio de variáveis definidas pelo desenvolvedor: defina uma variável para cada parâmetro no arquivo kettle.properties e insira-as nos lugares adequados usando a sintaxe ${VARIÁVEL}. O início é tedioso, como na opção anterior, mas é mais flexível pois basta mudar a variável no kettle.properties para propagar seu valor por todo processo. É a melhor opção quando temos vários projetos, pois podemos criar lotes de variáveis para cada um;
  3. Definindo valores das variáveis-default do PDI: esse método é de longe o mais prático para quem lida com um só projeto, pois você não precisa alterar nada em nenhuma transformação ou job. Cada campo das definições de log possui uma variável default. Definindo o valor destas no kettle.properties, o PDI configura a captura do log automaticamente. Por outro lado, se você trabalhar em mais de um projeto, vai precisar trocar essas variáveis sempre que mudar de projeto.

Alguns truques facilitam a vida do desenvolvedor: ao invés de configurar manualmente o log em todos os artefatos, crie modelos de transformação e job já configurados. Daí, quando precisar criar uma nova transformação/job, use o modelo: duplique o arquivo ou abra e salve com outro nome e comece dali. Meus modelos não apenas possuem os logs pré-configurados, como ainda deixo notas e padrões de documentação pré-preenchidos.


As variáveis são definidas no arquivo <diretório do usuário>/.kettle/kettle.properties. O Spoon oferece uma interface para fazer essa edição sem precisar sair da interface gráfica: clique no menu Edit e escolha a opção Edit the kettle.properties file. Aparecerá uma janela listando todas as variáveis default, mesmo que estejam vazias, além de todas as variáveis definidas pelo desenvolvedor:

Janela de edição do conteúdo do arquivo kettle.properties (variáveis.)
Janela de edição do conteúdo do arquivo kettle.properties (variáveis.)

Lembre-se de fechar o Spoon antes de editar o arquivo diretamente. Caso contrário, não apenas ele não vai ver os novos valores e variáveis, como ainda corre-se o risco de elas serem apagadas.

Um último detalhe: quase todos os logs são capturados por default. Quase: o de performance de passo, que é o que mais gera linhas no banco, está desligado por default. Para ativá-lo marque o checkbox Enable step performance monitoring? na aba Monitoring (a última na versão 5.4) das propriedades da transformação:

Ligue o checkbox para capturar o rendimento de cada passo da transformação.
Ligue o checkbox para capturar o rendimento de cada passo da transformação.

Criando as Tabelas

Como tudo no Spoon, sempre que algo escreve em uma tabela, um botão que permite criar ou ajustar essa tabela automaticamente. Para criar qualquer tabela de log basta preencher seus dados de conexão e nome, e clicar no botão SQL no fundo da janela de propriedades:

Criando as tabelas de log de transformação com ajuda do botão SQL.
Criando as tabelas de log de transformação com ajuda do botão SQL.

Se você preencher todos os parâmetros antes e deixar o botão de SQL para o fim, o Spoon vai te dar um monte de janelas, uma para cada tabela. O mesmo vale os logs de jobs.

Analisando Logs

Para os exemplos vamos usar o log gerado pela repetição do processo de carga do Beltrano S/A, de mil pedidos. Esse backup está disponível aqui, como um pacote RAR. Consulte as instruções de restauração da base Beltrano, lembrando apenas de substituir o nome do arquivo para o do arquivo da base de logs.

Vamos ver dois relatórios tão simples quanto úteis:

  • Logs de jobs e transformações
  • Histórico de performance

Logs de Jobs e Transformações

Quem cuida de processos de ETL sabe que a principal pergunta que se faz é “Rodou? Deu certo? O que aconteceu?”

Ok, são três perguntas, mas no fundo todas elas querem saber a mesma coisa: se o processo funcionou ou não, e o que aconteceu, se tiver dado erro.

A forma mais simples de respondê-las seria olhar o log de texto, o relato de tudo que se passou durante o processamento. É o primeiro lugar que devemos olhar porque é ali que estão as mensagens de erros. Eu chamo esse tipo de relatório simplesmente de “Relatório de Log”: Log de Jobs e Log de Transformações. Ele mostra um cabeçalho com parâmetros do objeto sendo examinado, como datas, status e duração, e logo abaixo o conteúdo de texto do processamento. A consulta que eu uso é assim:

Transformação

SELECT
     'Duracao em Segundos' as categoria,
     id_batch,
     transname,
     status,
     lines_read,
     lines_written,
     lines_updated,
     lines_input,
     lines_output,
     lines_rejected,
     replaydate,
     logdate,
     extract(hour from (logdate - replaydate))*60*60 +
          extract(minute from (logdate - replaydate))*60 +
          extract(second from (logdate - replaydate)) as duracao,
     log_field
FROM
     transformation

Job

SELECT
     'Duracao em Segundos' as categoria,
     id_job,
     jobname,
     status,
     lines_read,
     lines_written,
     lines_updated,
     lines_input,
     lines_output,
     lines_rejected,
     replaydate,
     logdate,
     extract(hour from (logdate - replaydate))*60*60 +
          extract(minute from (logdate - replaydate))*60 +
          extract(second from (logdate - replaydate)) as duracao,
     log_field
FROM
     job

Note a diferença entre os nomes dos campos dos dois artefatos (job e transformação), mas como mesmo assim são parecidos.

Essas consultas retornam todos os logs, de todas as transformações e jobs, o que é uma coisa inútil – imagine ter que varrer centenas, milhares de páginas atrás de um job ou outro! Por isso eu filtro essa consulta com dois prompts: um para nome do artefato e outro para seu batch, ou lote. As consultas para nomes são assim:

Lista de nomes de transformações:

SELECT DISTINCT transname
FROM transformation
ORDER BY transname ASC

Lista de nomes de jobs:

SELECT DISTINCT jobname
FROM job
ORDER BY jobname ASC

Quando o prompt de nome é preenchido, o prompt de lote fica disponível. As consultas para lotes são:

Lista de lotes de transformações:

SELECT id_batch,replaydate
FROM transformation
WHERE transname=${nome_transformacao}
ORDER BY id_batch DESC

Lista de lotes de jobs:

SELECT id_job,replaydate
FROM job
WHERE jobname=${nome_job}
ORDER BY id_job DESC

Com os dois prompts preenchidos (que estão marcados como obrigatórios, a propósito), o relatório roda:

Relatório de log de transformação.
Relatório de log de transformação.

Histórico de Performance

O mesmo resultado é obtido no relatório de jobs e seria redundante mostrá-lo tal como está. Vamos avançar um pouco, e mostrar o relatório de jobs com um pouco mais de informações: um histórico de duração.

Depois de saber “se deu certo”, o aspecto mais importante do ETL é sua repetibilidade. Afinal, se montamos um processo acreditando que, todo dia, ele vai rodar em menos de uma hora, precisamos saber se isso está acontecendo ou não.

Poderíamos usar o relatório anterior e, manualmente, examinar os tempos de um mesmo job ou transformação, em várias corridas ao longo de um período – uma semana, por exemplo. Trabalhoso. Bom, nós somos o pessoal da Inteligência de Negócios ou não? Como seria um vexame ter tanto trabalho, vamos ser mais práticos: vamos colocar um gráfico das várias execuções.

Pegamos o mesmo relatório anterior e acrescentamos uma nova consulta: a lista da duração das últimas X execuções em ordem crescente:

SELECT * FROM
(SELECT
     'Duracao em Segundos' as categoria,
     id_job,
     to_char(replaydate, 'DD/MM/YY HH24:MI:SS') as replaydate,
     extract(hour from (logdate - replaydate))*60*60 +
     extract(minute from (logdate - replaydate))*60 +
     extract(second from (logdate - replaydate)) as duracao
FROM job
WHERE jobname=${nome_job}
ORDER BY id_job DESC
LIMIT 30) AS X
ORDER BY id_job ASC

O SELECT interno obtém uma lista das últimas 30 execuções do job nome_job (o nome do parâmetro que contém a seleção do usuário). O SELECT externo inverte a ordem para que o gráfico seja plotado corretamente. O resultado dessa consulta para, por exemplo, o job Popula Tabelas Dependentes, é:

categoria id_job replaydate Duracao
Duracao em Segundos 2 23/02/16 20:34:24 1.064
Duracao em Segundos 5 23/02/16 20:51:37 0.671
Duracao em Segundos 7 23/02/16 20:54:54 0.655
Duracao em Segundos 11 23/02/16 21:01:08 0.652
Duracao em Segundos 14 23/02/16 21:07:54 0.742

Como um relatório pode ter apenas uma consulta ativa, e o relatório tal como está já usa uma, precisamos adicionar um sub-relatório para poder usar essa nova query. Neste sub-relatório, que herda essa consulta, adicionamos apenas o elemento de chart. Eu usei um gráfico de linhas, mas poderíamos usar qualquer outro tipo – barras, bullets, área etc.

Sub-relatório com consulta e parâmetro herdados do relatório principal.
Sub-relatório com consulta e parâmetro herdados do relatório principal.

Rodando o relatório o PRD vai exibir o prompt, já visto na figura acima. Já ao selecionar um job o gráfico será preenchido. Após selecionarmos um dos lotes – uma das corridas ou execuções do job – aparece o log logo (hehe) abaixo do plot.

Resultado: log do job selecionado, com visão simultânea das últimas execuções.
Resultado: log do job selecionado, com visão simultânea das últimas execuções.

Você pode baixar esses relatórios neste link.


Todos os materiais foram criados com a suite 5.4 do Pentaho. Se você tentar usar, e não conseguir, deixe um comentário que eu tento te ajudar.


Conclusão

Com um pouco mais de trabalho – configurar a captura de log e criar os relatórios – o gestor de ETL pode conseguir uma riqueza de informações sobre seu processo. Entre outros benefícios, o gerente de ETL passa a ser capaz de dizer, em poucos minutos, com poucos cliques, se o processo rodou hoje, se demorou mais, se deu algum erro e vários outros detalhes (incluindo volume processado e tempo de cada processamento.)

Outra função importante servida pelos logs é apoio na melhoria do processo. No próximo post veremos como usar os dados de performance das transformações para analisar o perfil de processamento e identificar gargalos.

Até lá! ;-)