segunda-feira, 26 de setembro de 2011

Populando fatos e dimensões no PDI (Kettle)

Dando continuidade ao uso de componentes que podem nos ajudar na etapa de estagiamento, que é uma das etapas na construção de um DW, vamos mostrar os componentes que poderiam ser úteis para popularmos as tabelas dimensão e a tabela fato.

Em uma tabela dim_cliente ou dim_produto, por exemplo, não existe mistério.   As tabelas dimensão são responsáveis por guardar as descrições, ou seja, nada de métricas por aqui.    O importante, é entender que além das descrições, guardaremos o código dos clientes e dos produtos na base relacional (base utilizada pelo sistema, pelas tabelas Cliente e Produtos), e além disso, teremos um NOVO código para cada um desses valores.
Aconselho iniciarmos o ID da tabela dim_cliente, por exemplo, com um número bem acima de 1.   Dessa forma, evitaremos facilmente coincidir os códigos da tabela relacional e da dimensão.
Poderíamos modelar nossa tabela dim_cliente com as colunas:
  • ID_CLIENTE (codigo do cliente para esta tabela, preferencialmente começando por um número alto)
  • NM_CLIENTE (campo com a descrição, ou seja, o nome do cliente)
  • CD_CLIENTE_RELACIONAL (codigo do cliente na base relacional)
Mas para que usaremos esta coluna (cd_cliente_relacional) no nosso DW?   Como o foco deste post não é explicar os conceitos de modelagem de um DW, até porque o material existente sobre o tema é extenso, basta-nos dizer que, ao popularmos nossa tabela fato com os eventos, como as vendas de um produto para os clientes de nossa loja, por exemplo, extrairemos os dados da base relacional e verificaremos quais os novos codigos de cada cliente fazendo a comparação pelo código da base relacional, que também está gravado na dimensão (do contrário teríamos que fazer esta comparação pelo nome, o que não é aconselhável).

A tabela Fato, que pode ser uma fato_vendas, por exemplo, teria as colunas:
  • ID
  • ID_CLIENTE (cliente que comprou)
  • ID_TEMPO (código indicando a data da compra)
  • QUANTIDADE (quantidade de produtos que o cliente comprou neste período)
E como poderíamos ter um código para o tempo?  Podemos modelar nossa dimensão tempo da seguinte forma:
  • ID_TEMPO (id da tabela)
  • DATA (data completa, ex: 01/01/2011)
  • ANO (inteiro indicando o número da data)
  • MES (idem)
  • DIA (idem)
Poderíamos ter as colunas hora, minuto e até segundo, se a necessidade de agruparmos os dados na tabela fato fosse diferente, mas em nosso exemplo, utilizaremos o dia como menor valor.
O  figura abaixo ilustra um ETL que popula a tabela dim_tempo instantaneamente, sendo necessário apenas indicar uma data inicial, o critério para soma (dias, horas, minutos, etc) e o número a somar (100 dias, 100 horas, 100 minutos, etc).   Apenas fornecendo estas informações, teremos nossa tabela dim_tempo populada em segundos, considerando até milhares de anos.
Para fazer o download do arquivo KTR, para manipulá-lo em sua própria máquina, clique aqui.



O componente Gera Linhas é um Generate Rows, utilizado apenas para definir quantas linhas vamos colocar em nossa tabela dim_tempo.    Neste caso, colocaremos 1000 linhas, o que significa que criaremos uma linha para cada dia, começando do dia 01/01/2011.
O componente Adiciona Dias é um Add Sequence, utilizado para gerar uma sequencia numérica e adicioná-la ao fluxo, ou seja, cada linha receberá um número, começando de 1 e incrementado em 1, conforme definido dentro do componente.
O componente Get Data Inicial recebe uma data inicial, o número que será somado à data e como ela será incrementada (em dias, anos, meses, etc).   Em nosso exemplo está definido que será em dias.
O componente Cria ID é um outro Add Sequence, que desta vez gerará um ID para nossa dim_tempo.
O Componente JS Quebra Tempo é um componente para scripts em javascript.    Neste caso estamos utilizando-o para "particionar" a data, separando o dia, mês e ano que serão inseridos de forma numérica em nossa dim_tempo.
Por último temos um Table Output renomeado para Popula Dim_Tempo, que receberá as linhas provenientes do fluxo para gravar na tabela dim_tempo.
Para entender melhor o funcionamento de cada componente, aconselho a fazer o download do mesmo através do link acima.

Chegamos finalmente ao objetivo principal de nosso post.    
Considerando que temos em nossa base relacional uma tabela que relacione cada venda efetuada pelo sistema, cadastrando o código do cliente e a data da venda, por exemplo, faremos agora, de forma simples, a carga destes dados e seu devido agrupamento para dentro de nossa tabela fato.
Como a tabela fato registra apenas métricas e códigos, indicando a ligação com as tabelas de dimensão, utilizaremos o componente Database Lookup diversas vezes para procurar o código das tabelas de dimensão que correspondem ao valor de cliente e tempo da base relacional, além do componente Group By, responsável por agrupar a quantidade de vendas por dia, por exemplo, feitas para cada cliente registrado em nosso DW, na tabela dim_cliente.
Veja na figura abaixo como ficou nosso processo de carga da tabela fato_vendas:



Para fazer o download deste ETL, clique aqui.

O exemplo utilizado aqui é extremamente simples e não reflete a realidade, visto que nunca iríamos modelar um DW e criar uma tabela de fato vendas (por exemplo) sem levar em conta os produtos vendidos, as regiões, lojas, fornecedores, etc.
Nosso objetivo, que esperamos ter sido alcançado, é dar uma visão inicial de como utilizar os componentes que nos ajudarão a popular os fatos e as dimensões, abordando principalmente a dimensão tempo, fruto de diversas dúvidas e discussões.

No próximo post voltaremos a explicar de forma detalhada sobre mais alguns componentes do PDI.

12 comentários:

  1. Luciano boa tarde!
    Estou precisando de uma ajuda, e não consegui achar um caminho, tenho uma tabela vendas e uma tabela historico_custos, na historico são guardados os custos e atualizados quanto tem alguma alteração exemplo: posso ter um valor de um produto que está sendo vendido hoje, mas o custo dele é de maio por exemplo.

    Meu problema: não consegui, no momento de carregar a fato, fazer uma relação que quando encontrar o produto 1 eu busque o ultimo custo dele na tabela historico_custo, onde a data do mesmo seja <= a data da venda. O banco é oracle, ele tem algumas restrições no caso da sub select, onde seria necessário um order by desc, e ele nao permite esse detalhe, por isso tenho que ajustar de outra forma.

    att

    ResponderExcluir
    Respostas
    1. No seu caso, acredito que o ideal é fazer o seguinte:
      1- Crie um primeiro fluxo com um table input para capturar os dados do produto;
      2- Crie um segundo fluxo com outro table input para capturar os dados da venda;
      3- Neste segundo fluxo filtre apenas os custos que te interessam (data <= à data da venda);
      4- Utilize o step "Group by", dentro da pasta "Statistics" para pegar o último custo do produto, através da função MAXIMUM;
      5- Utilize o step "Stream Lookup" ou "Merge Join" para associar os produtos que estão no primeiro fluxo com
      os custos mais recentes, que estão no segundo fluxo.

      Excluir
  2. Luciano, o ETL do Fato não está mais disponível para download. Tens como disponibilizar?

    ResponderExcluir
  3. Luciano, bom dia.

    Poderia me ajudar com uma situação?

    Criei um ETL para criar uma fato em um DW e um JOB para atualizar todas as fatos diariamente, o problema é que quando o JOB é executado, ele lança todos os dados novamente na tabela fato dentro do DW, duplicando todas as informações...Quando faço a análise pelo cubo OLAP ele traz todas as informações.

    ResponderExcluir
  4. Boa tarde,

    Os arquivos não estão mais disponível para download.

    Alguém poderia disponibilizar ou me enviar por favor?

    ResponderExcluir
  5. O table output duplica os dados se executado duas vezes. Qual forma voce indicaria para atualização do dw diariamente. To utilizando o insert/Update esta muito lento.

    ResponderExcluir
    Respostas
    1. tenho o mesmo problema... conseguiu resolver?

      Excluir
    2. Use insert/update dai os dados não vão ser duplicados

      Excluir
  6. Boa Tarde, poderia me enviar o ETL Acima por Favor.
    jfernandocv@gmail.com

    ResponderExcluir
  7. poderia disponibilizar o etl da montagem da dimensao tempo novamente. meu email é lipe-bs@hotmail.com

    ResponderExcluir