Joins rows (cartesian)
Juntar linhas e colunas em um único local é a principal tarefa dentro de um ETL. Muitas vezes o que temos de fontes espalhadas e que se complementam não está escrito.
Com esse cenário em mente, vamos começar neste post a entender como o Pentaho trabalha e quais são as opções de Join que ele permite.
O Pentaho possui:
- Database join
- Join rows (cartesian product)
- Merge join
- Merge row
- Multiway join
- Sorted merge
- Xml join (posterior)
Estes são os tipos que o PDI habilita conhecer e utilizar.
Para este post de hoje, veremos como o Join Rows (produto cartesiano – Cross Join na linguagem SQL) funciona quando executado e, desvendar esse pequeno mistério sobre como unir linhas e colunas com joins.
Veja o esquema básico de exemplo:
Os dummys foram adicionados para facilitar a seleção do campo principal.
JOINS ROWS (CARTESIAN PRODUCT)
O Join cartesiano tem um entendimento um pouco mais simples já que ele pega as linhas de uma fonte de dados, multiplica pelo número de linhas da outra fonte e retorna o resultado.
Aqui temos a configuração mostrando que sim, é bem básico configurar o cross join no PDI.
As condições utilizadas para o resultado são diversas, desde que, respeite as colunas das tabelas.
É o mais básico entre os existentes e utilizado em casos especiais, como por exemplo, para tratamento de colunas que foram divididas em linhas à serem agrupadas.
Uma dica importante para uso desta transformação é utilizar o data stream de maior quantidade de dados como a stream principal. Essa escolha da ‘maior’ stream se justifica pois o PDI lida melhor aplicando a stream menor na stream maior do que o contrário.
Então, se uma stream sua tem 1mi de linhas e outra apenas 1000, utilize a stream de 1mi como principal.
Nesta nova estrutura, criei duas novas fontes de dados modificando a stream. Sendo uma gerando 10000 linhas e a outra 1000 linhas.
Para melhor ilustrar a situação, veja esse novo teste onde eu recriei a fonte de dados reconfigurando o Join Rows. Perceba que o main step passou a ser a fonte prodcat que possui a menor quantidade de linhas.
Ao executar essa stream, ela gerou 10 milhões de linhas. Veja as métricas de resultado final que o Pentaho fornece.
Nesse processo utilizando a fonte prodcat, perceba que nos dois primeiros pontos de análise, generate rows (caixa vermelha), o PDI mesmo gerando maior quantidade de linhas em um dos processos, conseguiu realizar essa tarefa em maior velocidade do que a que gerou uma menor quantidade.
É possível refletir o seguinte: “tudo bem, mas a task generate rows 2 gerou uma quantidade menor e não precisou de tanta velocidade”.
OK, pode até pensar assim, mas veja que a stream com uma quantidade 10x menor, utilizou cerca de 1/4 da velocidade para finalizar a escrita.
Outra análise que corrobora com a afirmação acima é comparar o tempo que o PDI demorou para ler e escrever as linhas do step generate rows no dummy. Mais uma vez, veja que no prodcat, o dummy demorou quase 3/4 de r/s para ter uma quantidade bem menor de linhas escritas.
E ao final, no processo join rows (cartesian product – sublinhado em roxo) o PDI demorou cerca de 28.4s para ler, multiplicar e escrever as 10 mi de linhas que foram geradas. Isso tudo é claro, utilizando a fonte prodcat como stream principal.
Após essa análise, vamos ver como se saiu utilizando a fonte de dados subcat como stream principal. Vamos analisar os mesmos fatores.
Atentem para as mesmas métricas que analisamos no passo anterior. Como podemos ver, os principais processos envolvidos na transformação continuaram mais rápido para os steps que são provenientes do subcat e com um agravante: o processo de read/write no dummy Prodcat precisou de mais velocidade para ler e escrever 1000 linhas do que o Subcat que fez o mesmo processo com 10x mais dados.
Aqui corrobora que a task de prodcat mesmo com uma quantidade menor de linhas, continua exigindo maior quantidade de recursos. Seja diretamente, quando exige maior velocidade para ler e escrever menos dados, seja por projeção, caso aumentássemos a quantidade de dados.
E para uma análise mais simples, veja o tempo de conclusão consolidado pelo PDI.
A primeira imagem se trata do join rows(cartesian product) com o step prodcat como stream principal.
E agora, o mesmo processo com a stream subcat como principal.
EXTRA
Fiz um teste habilitando a opção de cópia do processo ao qual dobrei o valor testando primeiro como se saíria o ETL completo com a fonte prodcat como primária para o join.
Veja o gráfico de resultados.
E abaixo, o processo com a stream subcat como primária.
Mesmo com o recurso de ‘multithread‘ habilitado, utilizar a fonte com maior quantidade de dados continua sendo a melhor opção.
E se souberem quantas linhas serão processadas no ETL, aumentem o Max Cache Size (in rows) para um número que seja maior, mas não tão maior.
Assim, o Pentaho tem um cache de memória maior para armazenar as linhas tornando o ETL mais rápido.
Deixo claro que esse teste foi executado no meu notebook antigo que não possui tantos recursos de hardware! No meu pc de estudos, as transformações chegaram a ser 5x mais rápidas, no mínimo.
CONCLUSÃO
Este foi o primeiro post da série sobre Joins utilizando Pentaho. A ideia é fomentar a base de união entre diversas fontes para, após, entrar de vez nas questões que envolvem lookup.
Embora não muito utilizado, o join no formato produto cartesiano pode entregar boas soluções de tratamento de dados, principalmente quando ocorre algum split.
Se for utilizar esta transformação em específico, preste atenção na escolha entre as fontes principais e secundárias. Isso vai lhe poupar um bom tempo de execução, principalmente em volume que envolve bilhões de linhas.
Habilitar cópia do processo para dividir a tarefa, apresenta um bom ganho de performance, façam o teste por si e vejam!
Embora pareça complicado, este foi um post bem simples mas que quis mostrar o porque devemos escolher a stream com maior fonte como base!
Tenham uma boa semana, saúde!