window.lintrk('track', { conversion_id: 13086145 }); Forum posts
top of page

Posts do fórum

rodrigo.kartcheski
31 de mai. de 2023
In Big Data
E aí pessoal tudo bem? Vamos criar nosso primeiro pipeline usando Apache Beam? O primeiro passo para criar uma PCollection é criar um pipeline, que representará a sequência de transformações que serão aplicadas aos seus dados. Lembrando que estamos considerando que o Apache Beam já está instalado. Crie arquivo chamado first_pipe.py e salve em um diretorio. e cole o script abaixo. import apache_beam as beam # Crie um Pipeline object pipeline = beam.Pipeline() # Crie uma PCollection pcoll = pipeline | "Create PCollection" >> beam.Create([1, 2, 3, 4, 5]) # Execute o pipeline pipeline.run() Neste exemplo criamos um pipeline simples, com uma pcoll contendo 3 colunas usando a classe beam.Pipeline(). Em seguida, usamos o operador | (pipe) para definir uma transformação na qual criamos uma PCollection usando o beam.Create() transform e passamos uma lista de tuplas como os elementos da Pcollection. Finalmente, chamamos o método pipeline.run() para executar o pipeline e processar a Pcollection. Neste exemplo, como não temos transformações adicionais, o pipeline apenas cria a PCollection e a executa. No entanto, observamos que nossa pcoll ficou nome de colunas, então decidimos acrescentar uma transformação para incluir o nome das colunas. Note a linha 11 na imagem abaixo, usamos a transformação Map para nomear as colunas na PCollection pcoll e passamos uma função lambda, um tipo de função anônima que pode ser usada em Python. A função lambda neste caso define o nome das colunas: id, name, age. Também acrescentamos a linha 13, para podemos visualizar os dados impressos. O resultando do dicionario impresso na tela. Por hoje é isso pessoal, espero que tenham gostado.
Minha primeira PCollection no Apache Beam content media
0
0
18
rodrigo.kartcheski
31 de mai. de 2023
In Big Data
Introdução à álgebra relacional: Uma breve introdução sobre o que é álgebra relacional. A relação entre matemática, álgebra relacional e teoria dos conjuntos é estreita e interdependente. Em seu artigo de 1970, "A Relational Model of Data for Large Shared Data Banks", Edgar F. Codd apresentou o modelo relacional de banco de dados, que se baseia na álgebra relacional e na teoria dos conjuntos. A álgebra relacional é um sistema formal matemático que permite a manipulação de relações (tabelas) e a realização de operações sobre elas, como união, interseção, diferença, produto cartesiano e junção. A teoria dos conjuntos também é uma parte fundamental da álgebra relacional, já que as operações que são realizadas nas tabelas são semelhantes às operações que podem ser realizadas em conjuntos. O modelo relacional de banco de dados foi uma revolução na época em que foi proposto, pois apresentou uma abordagem completamente diferente de armazenamento e manipulação de dados em relação aos modelos hierárquicos e em rede que eram utilizados na época. O modelo relacional permite a organização dos dados em tabelas com linhas e colunas, fornecendo uma estrutura clara e consistente para a manipulação dos dados. A álgebra relacional e a teoria dos conjuntos também têm aplicações em várias áreas da matemática e da ciência da computação, como a lógica, a teoria dos grafos e a teoria da computação. A álgebra relacional, em particular, é usada não apenas na manipulação de bancos de dados, mas também em áreas como redes neurais, aprendizado de máquina e processamento de linguagem natural. A Álgebra relacional é uma linguagem matemática que descreve operações em conjuntos de dados estruturados em forma de tabelas, conhecidos como relações. Essa linguagem formal é utilizada em bancos de dados relacionais para definir consultas e operações de manipulação de dados. Algumas das operações que podem ser realizadas pela Álgebra relacional incluem seleção (filtragem de dados), projeção (selecionando colunas específicas), junção (combinando informações de várias tabelas), união (combinando informações de duas tabelas), intersecção (retornando informações que aparecem em ambas as tabelas), entre outras. A Álgebra relacional é amplamente utilizada em sistemas de gerenciamento de bancos de dados relacionais para otimização de consultas e operações. Ela é usada em conjunto com as linguagens SQL (Structured Query Language) para construir consultas e operações de banco de dados, permitindo a realização de consultas precisas e eficientes em bancos de dados relacionais. O PySpark, que é a interface Python do framework Apache Spark, usa a álgebra relacional em sua API para processamento de dados distribuído. O Spark SQL, que é o módulo de processamento de dados estruturados do Apache Spark, é baseado em álgebra relacional e oferece uma API semelhante à SQL para consulta e manipulação de dados em conjunto com o PySpark. A API do Spark SQL permite aos usuários escrever consultas em SQL e também fornece suporte para funções de agregação, junção, filtro, seleção e outras operações de álgebra relacional. Além disso, o Spark SQL também oferece suporte à API DataFrame, que permite a manipulação de dados estruturados em Python e é baseada em conceitos de álgebra relacional. A álgebra relacional é essencial para o processamento de dados estruturados em bancos de dados relacionais e em outras aplicações que envolvem manipulação de tabelas e conjuntos de dados. O seu uso permite a criação de consultas precisas e eficientes em bancos de dados, bem como a realização de operações sofisticadas em processamento de dados distribuído, como no caso do PySpark e do Spark SQL. Por fim, a compreensão dos conceitos de álgebra relacional e teoria dos conjuntos é fundamental para profissionais da área de ciência da computação e tecnologia da informação que desejam trabalhar com bancos de dados e processamento de dados estruturados. É um conhecimento fundamental para o desenvolvimento de sistemas e aplicações que lidam com dados e informações de forma eficiente e organizada. O BIG Data é caracterizado pelo grande volume, velocidade e variedade de dados que precisam ser armazenados, processados e analisados. Nesse contexto, a Álgebra Relacional é uma das técnicas que pode ser usada para lidar com esses desafios, já que ela permite que consultas precisas e eficientes sejam realizadas em grandes volumes de dados. Uma das abordagens mais comuns para lidar com BIG Data usando a Álgebra Relacional é a utilização do MapReduce, um modelo de programação que permite o processamento distribuído de grandes volumes de dados em clusters de computadores. O MapReduce é uma técnica que pode ser usada para executar operações de Álgebra Relacional em grandes volumes de dados. O Apache Hadoop é um framework de processamento distribuído de dados que implementa o modelo MapReduce. O Hadoop é amplamente utilizado em soluções de BIG Data, como o processamento de logs, a análise de dados em tempo real e a análise de dados de mídia social. O Apache Spark é outro framework de processamento distribuído que é amplamente utilizado em soluções de BIG Data. O Spark oferece suporte para a Álgebra Relacional por meio de sua API Spark SQL. A Spark SQL é uma API que oferece suporte para a execução de consultas SQL em dados distribuídos usando o Spark. Além disso, o Spark SQL oferece suporte para funções de agregação, junção, filtro, seleção e outras operações de Álgebra Relacional. Consulte o aritgo original aqui: https://dl.acm.org/doi/10.1145/362384.362685 Operações básicas: Descrição das operações básicas da álgebra relacional. As operações básicas da álgebra relacional incluem: • Seleção (σ): A seleção é usada para recuperar tuplas de uma tabela que atendem a uma condição específica. Por exemplo, selecionar todos os funcionários com idade superior a 30 anos. • Projeção (π): A projeção é usada para recuperar colunas específicas de uma tabela. Por exemplo, projetar apenas os nomes dos funcionários em uma tabela. • União (⋃): A união é usada para combinar duas tabelas com o mesmo esquema e retornar uma tabela que contém todas as tuplas das duas tabelas originais, sem duplicatas. • Interseção (⋂): A interseção é usada para comparar duas tabelas e retornar uma tabela que contém apenas as tuplas que aparecem em ambas as tabelas originais. • Produto cartesiano (×): O produto cartesiano é usado para combinar cada tupla em uma tabela com cada tupla em outra tabela, criando uma nova tabela que contém todas as combinações possíveis de tuplas. • Junção (⨝): A junção é usada para combinar tuplas de duas tabelas relacionadas com base em uma condição de junção. Por exemplo, unir as tabelas de funcionários e departamentos com base no departamento em que cada funcionário trabalha. Essas operações básicas da álgebra relacional podem ser combinadas para realizar consultas mais complexas em um banco de dados relacional. Seleção Na álgebra relacional, a seleção é usada para selecionar informações específicas de uma tabela. É como usar um filtro para selecionar apenas as informações que você precisa. É como usar um filtro em um aplicativo de fotos para selecionar apenas as fotos que contêm determinadas pessoas. A seleção usa símbolos especiais, como o σ, para mostrar que estamos fazendo essa operação. Usando a seleção, podemos filtrar as informações com base em regras que definimos, como idade ou salário. Por exemplo, podemos usar a seleção para encontrar apenas funcionários com mais de 30 anos em uma tabela de funcionários. Dessa forma, podemos trabalhar apenas com as informações que são importantes para nós, economizando tempo e tornando as coisas mais fáceis. Neste exemplo, "Idade > 30" é a condição de seleção que estamos usando para filtrar as tuplas desejadas. A operação de seleção retornará uma tabela que contém apenas as tuplas (linhas) da tabela "Funcionários" em que a idade é maior que 30 anos. A operação de seleção é uma das operações básicas da álgebra relacional e é usada em conjunto com outras operações para realizar consultas mais complexas em um banco de dados relacional. Exemplo: Selecionar todos os clientes que têm uma idade superior a 25 anos e um salário superior a R$ 5.000,00: σ(Idade > 25 AND Salário > 5000) (Clientes) Em SQL: SELECT * FROM Clientes WHERE Idade > 25 AND Salário > 5000; Pyspark: from pyspark.sql.functions import col clientes.select("*").where((col("Idade") > 25) & (col("Salário") > 5000)) Pandas: clientes[(clientes['Idade'] > 25) & (clientes['Salário'] > 5000)] Apache beam: clientes | beam.Filter(lambda row: row['Idade'] > 25 and row['Salário'] > 5000) Neste exemplo, a operação de seleção é usada para filtrar as tuplas da tabela "Clientes" que atendem à condição especificada, que é "Idade > 25 AND Salário > 5000". A operação de seleção retornará uma tabela com todos os clientes que têm mais de 25 anos e um salário superior a R$ 5.000,00. Projeção A projeção na álgebra relacional é como uma lupa que nos permite examinar uma tabela e ver apenas as informações que são importantes para nós. É uma forma de selecionar somente as colunas de uma tabela que queremos ver, criando uma nova tabela com essas informações. Por exemplo, imagine que temos uma tabela de funcionários com muitas informações, como nome, idade, salário, endereço e assim por diante. Mas, se quisermos ver apenas o nome e o salário dos funcionários, podemos usar a projeção para criar uma nova tabela que contenha apenas essas informações. A projeção é indicada pelo símbolo grego π, e podemos usá-la para escolher apenas as colunas que queremos ver, ignorando as outras colunas que não são importantes para nós. Por exemplo, se quisermos ver apenas o nome e o salário dos funcionários, podemos usar a projeção da seguinte forma: π(Nome, Salário) (Funcionários). Dessa forma, a nova tabela que criamos terá apenas o nome e o salário dos funcionários, facilitando muito o trabalho com essas informações. A projeção é uma ferramenta útil para trabalhar com grandes quantidades de informações, pois permite que selecionemos apenas as informações importantes e reduzimos a quantidade de dados que precisamos processar. Exemplo de projeção Vamos supor que temos a seguinte tabela "Funcionários" com as seguintes colunas: "Nome", "Idade", "Salário", "Departamento" e "Endereço". Para obtermos o resultado de uma nova tabela com as colunas "Nome" e "Departamento" podemos usar a operação de projeção da seguinte forma: π(Nome, Departamento) (Funcionários) Em SQL: SELECT Nome, Departamento FROM Funcionários; Em pyspark: from pyspark.sql.functions import col funcionarios_projetados = funcionarios_df.select(col("Nome"), col("Departamento")) Em Pandas: funcionarios_projetados = funcionarios_df[["Nome", "Departamento"]] No Apache Bream: def projetar_funcionarios(funcionario): return {"Nome": funcionario["Nome"], "Departamento": funcionario["Departamento"]} with beam.Pipeline() as pipeline: funcionarios_pcoll = pipeline | beam.Create(funcionarios) funcionarios_projetados = funcionarios_pcoll | beam.Map(projetar_funcionarios) União A união na álgebra relacional é uma operação que combina duas tabelas em uma só, sem repetir as linhas que aparecem nas duas tabelas. Por exemplo, se você tem duas tabelas com informações sobre funcionários, como nome e cargo, pode usar a união para combiná-las em uma só tabela que contém todas as informações. A operação de união é representada pelo símbolo ∪ e é usada quando você deseja juntar duas tabelas com as mesmas colunas. Por exemplo, se você tem uma tabela "Funcionários" com nome, departamento e salário, e uma tabela "Contratados" com nome, departamento e data de contratação, pode usar a operação de união para combinar as duas tabelas em uma única tabela que contém todas as informações. Exemplo de união Suponha que você tenha duas tabelas: "Funcionários" e "Contratados", ambas com as mesmas colunas "Nome" e "Departamento", mas com informações diferentes. Para unir as duas tabelas em uma só, sem repetir as linhas que aparecem nas duas tabelas, podemos usar a operação de união. A operação de união é representada pelo símbolo ∪ e é usada da seguinte forma: Funcionários ∪ Contratados Em SQL: SELECT Nome, Departamento FROM Funcionários UNION SELECT Nome, Departamento FROM Contratados; Em pyspark: from pyspark.sql.functions import col resultado = funcionarios.select(col("Nome"), col("Departamento")).union( contratados.select(col("Nome"), col("Departamento")) Em Pandas: resultado = funcionarios[['Nome', 'Departamento']].merge( contratados[['Nome', 'Departamento']], how='outer' ) resultado = pd.concat([funcionarios[['Nome', 'Departamento']], contratados[['Nome', 'Departamento']]]).drop_duplicates() No Apache Beam: with beam.Pipeline() as pipeline: # Criando um PCollection para cada conjunto de dados pc_funcionarios = pipeline | 'Criar PC Funcionários' >> beam.Create(funcionarios) pc_contratados = pipeline | 'Criar PC Contratados' >> beam.Create(contratados) # Executando a operação de união dos conjuntos resultado = (pc_funcionarios, pc_contratados) | 'União' >> beam.Flatten() Interseção A Interseção é uma operação da álgebra relacional que consiste em comparar dois conjuntos de dados e mostrar somente os elementos que existem em ambos. Em outras palavras, é uma forma de encontrar a "parte em comum" entre os conjuntos. Por exemplo, se tivermos um conjunto A com os números {1, 2, 3, 4} e um conjunto B com os números {3, 4, 5, 6}, a interseção entre A e B seria o conjunto {3, 4}, já que esses são os únicos números que aparecem em ambos os conjuntos. Na linguagem da álgebra relacional, a Interseção é representada pelo símbolo de intersecção (∩). Então, se tivermos dois conjuntos de dados chamados "Funcionários" e "Gerentes", poderíamos usar a Interseção para encontrar os funcionários que também são gerentes (ou seja, estão presentes em ambos os conjuntos). Exemplo de interseção: O comando para realizar a operação de interseção na álgebra relacional é o "∩". Suponha que temos duas tabelas: uma tabela chamada "A" com as colunas "id" e "nome", e outra tabela chamada "B" com as colunas "id" e "email". Para realizar a interseção entre as tabelas, considerando apenas os que registros que possuem o mesmo "id" nas duas tabelas, utilizamos a seguinte operação que retorna uma nova tabela contendo apenas as linhas que possuem o mesmo valor de "id" em ambas as tabelas. A ∩ B No SQL: SELECT * FROM A INTERSECT SELECT * FROM B; No Pysark: resultado = dataframeA.intersect(dataframeB) No Pandas: resultado = pd.merge(df1, df2, on=['A', 'B'], how='inner') No apache Beam: resultado = ({'A': pc_A, 'B': pc_B} | 'Join com tipo inner join' >> beam.CoGroupByKey() | 'Selecionar chaves com valores em ambas as coleções' >> beam.Filter(lambda x: all(key in x[1] for key in ['A', 'B']))) Produto cartesiano O produto cartesiano é uma operação na álgebra relacional que combina todas as tuplas de duas relações diferentes para criar uma nova relação. Quando você tem duas relações A e B, o produto cartesiano de A e B resulta em uma nova relação que contém todas as combinações possíveis de tuplas de A e B. Por exemplo, se você tem duas relações A e B, onde A tem duas tuplas {a1, a2} e B tem três tuplas {b1, b2, b3}, o produto cartesiano entre A e B resultaria em uma nova relação com seis tuplas {(a1, b1), (a1, b2), (a1, b3), (a2, b1), (a2, b2), (a2, b3)}. Em outras palavras, o produto cartesiano cria todas as possíveis combinações de tuplas entre duas relações. É importante lembrar que o resultado do produto cartesiano pode ser muito grande, especialmente quando você tem muitas tuplas em suas relações. A fórmula matemática para calcular a combinação do produto cartesiano é simplesmente multiplicar o número de elementos do conjunto A pelo número de elementos do conjunto B. Assim, se A tem n elementos e B tem m elementos, o produto cartesiano de A e B terá n x m elementos. Ou seja, a fórmula é: |A x B| = |A| x |B| onde |A| é o número de elementos no conjunto A e |B| é o número de elementos no conjunto B. O símbolo "x" representa o produto cartesiano e "|" representa o tamanho do conjunto, ou seja, o número de elementos. Exemplo de operação cartesiano A = {1, 2, 3} B = {4, 5} O produto cartesiano A x B é a combinação de todos os elementos de A com todos os elementos de B, gerando uma nova relação, onde cada elemento da relação é uma tupla que contém um elemento de A combinado com um elemento de B. A x B = {(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)} No SQL: SELECT * FROM A CROSS JOIN B; No Pyspark: resultado = dfA.crossJoin(dfB) No Pandas: resultado = pd.merge(A.assign(chave=0), B.assign(chave=0), on='chave').drop('chave', axis=1) No Apache Beam: produto_cartesiano = ( pc1 | 'Combina com' >> beam.FlatMap(lambda x, pc2: [(x, y) for y in pc2], pc2=pc2) ) Junção (join) Junção na álgebra relacional é uma operação que combina duas tabelas (ou relações) a partir de uma condição definida. Essa condição é geralmente uma igualdade entre duas colunas que existem em ambas as tabelas. A junção retorna uma nova tabela que contém todas as colunas das tabelas originais, mas com as linhas combinadas onde a condição de junção é verdadeira. É como se você estivesse unindo duas peças de quebra-cabeça que se encaixam perfeitamente. Por exemplo, se você tiver uma tabela com informações de clientes e outra tabela com informações de pedidos, você pode juntá-las para obter uma tabela que mostre todos os clientes e seus pedidos correspondentes. Exemplo: Para obter informações sobre as notas dos alunos em uma determinada turma, você pode usar a operação de junção para combinar as duas tabelas com base na coluna Nome. O resultado será uma nova tabela que contém as informações de ambas as tabelas, mas apenas para os alunos da turma especificada. Alunos ⋈ Notas No SQL: SELECT Alunos.ID, Alunos.Nome, Notas.Disciplina, Notas.Nota FROM Alunos INNER JOIN Notas ON Alunos.ID = Notas.ID; No Pyspark: from pyspark.sql.functions import col join_df = alunos_df.join(notas_df, col("alunos_df.id_aluno") == col("notas_df.id_aluno"), "inner") No Pandas: juncao = pd.merge(alunos, notas, on='id_aluno', how='inner') No Apache beam: join = ( {'alunos': alunos, 'notas': notas} | 'CoGroupByKey' >> beam.CoGroupByKey() | 'Filtrar' >> beam.Filter(lambda x: x[1]['alunos'] and x[1]['notas']) | 'Map' >> beam.Map(lambda x: (x[0], list(x[1]['alunos'])[0], list(x[1]['notas'])[0])) ) Mais exemplos de joins O inner join a seguir é perfeito, tanto df1 quanto df2 estão organizados de forma que o resultado do relacionamento é perfeito, retornando a quantidade de linhas desejada. Nesta junção, era esperado outro resultado, no entanto, note que o id 2 sumiu afetando a regra de negocio. Analisando as duas tabelas, vemos podemos tirar o grupo da clausula do relacionamento. No exemplo abaixo criamos uma especie de intra-cartesiano, pois ambas as tabelas tem id duplicados. Absolutamente este não é o resultado esperado pela regra de negocio. Temos de nos certificar que uma das tabelas tenha valores únicos antes de fazer a operação de Join. É importante garantir que não haja duplicatas nos registros que serão usados para fazer o join, mas não é necessário que uma das tabelas tenha valores únicos. O join em si não repete registros, ele apenas combina as informações das tabelas baseado nas colunas especificadas. Se uma tabela tiver valores duplicados em uma ou mais colunas que estão sendo usadas para o join, então esses valores duplicados serão repetidos no resultado final, mas isso não significa que os outros valores serão excluídos. Não é necessário que uma das tabelas tenha valores únicos antes de fazer a operação de join. O que pode ser necessário, dependendo do caso, é garantir que não haja duplicatas nos registros que serão usados para fazer o join. No exemplo abaixo, se a tabela da direita tiver o id 1 repetido 2 vezes e a tabela da esquerda tiver os ids 1 e 2, o resultado final do join terá 2 linhas, uma para cada ocorrência do id 1 na tabela da direita e uma para o id 2 na tabela da esquerda. Ou seja, o id 2 ainda aparecerá no resultado final. Por hoje é isso pessoal, o assunto sobre álgebra relacional é extenso quando começamos explorar os desdobramentos.
Algebra relacional em operações de Big Data content media
0
0
7
rodrigo.kartcheski
21 de abr. de 2023
In Big Data
O Apache Beam é um modelo de programação que permite o processamento de dados distribuídos. Ele possui uma única API que pode ser usada para processar tanto Datasets quanto DataFrames. Ao criar um pipeline utilizando o Apache Beam, não é necessário se preocupar com o tipo de pipeline que está sendo construído, seja ele um pipeline em lote ou de streaming. A história do Apache Beam remonta a 2014, quando a Google começou a desenvolver um modelo de programação unificado para processamento de dados em batch e em tempo real. Esse modelo, inicialmente chamado de Dataflow Model, permitiria que os usuários definissem pipelines de processamento de dados portáteis e escaláveis que poderiam ser executados em diferentes motores de execução. Em 2015, a Google lançou uma versão beta do seu serviço de processamento de dados em nuvem, chamado de Google Cloud Dataflow, que usava o modelo de programação Dataflow. Nessa época, a Google também começou a trabalhar em uma implementação open source do modelo de programação, que mais tarde seria doada à Apache Software Foundation. O Apache Beam é um projeto ativo e em constante evolução, com uma comunidade de desenvolvedores dedicados que trabalham em melhorias e novos recursos. Em sua arquitetura, o Apache Beam é composto por Pipelines, Pcollections, Transformações, Runner Pipelines Para iniciar os processamentos no Apache Beam, é necessário construir um objeto Pipeline que servirá de referência para a criação dos conjuntos de dados do pipeline. É importante ressaltar que cada pipeline é responsável por executar um único job, que pode ser repetido diversas vezes. Podemos entender o pipeline como uma sequência de processos que formam um ciclo completo, abrangendo todo o processo, desde a entrada até a saída do processamento. Ele é responsável por ler, processar e gravar os dados de entrada e saída. Pcollections Pcollection é uma coleção de dados que faz parte da construção de um pipeline do Apache Beam, definida como "um conjunto de dados ou fluxo de dados". Diferentemente de uma tabela, essa coleção pode ser formada por qualquer combinação de dados, desde dados achatados no formato de tabela até dados aninhados como um documento JSON. A Pcollection não exige a conversão dos dados recebidos para um formato específico, como dataframe, e os dados são mantidos conforme o original, respeitando algumas convenções. Embora essa coleção aceite elementos de qualquer tipo, é necessário que eles sejam todos do mesmo tipo. Por isso, é importante que o desenvolvedor do Apache Beam aprimore seus conhecimentos em esquema de dados, pois tabelas SQL, Parquet, Avro, JSON e Kafka possuem esquemas específicos que precisam ser identificados para que determinados comandos sejam executados com sucesso. O Beam codifica cada elemento como uma string de bytes para que possa passar itens para trabalhadores distribuídos, conforme mencionado em sua página de programação. Transformações Uma transformação é um procedimento que modifica os dados em processamento. Ao receber uma ou mais PCollections como entrada, cada elemento é submetido a uma operação específica, resultando em uma ou mais PCollections como saída. As operações que uma transformação pode executar são diversas, abrangendo desde cálculos matemáticos, mudança de formato, agrupamento, leitura e gravação, filtragem para apresentar somente os itens relevantes, até a combinação de elementos em um valor único. No exemplo abaixo, vemos um Pipeline chamado Pipeline, com uma Pcoll chamada pcoll, que faz a leitura de uma lista de dicionários, e trata o elemento idade, convertendo-o para INT. Runner O runner, por outro lado, é um componente que determina como o pipeline será executado. Ele pode ser visto como uma espécie de ponte entre o pipeline e o executor, que traduz a especificação do pipeline em uma forma que o executor possa entender. O runner pode ser configurado para trabalhar com diferentes executores, dependendo do ambiente de execução e dos requisitos do pipeline. Alguns exemplos de runners populares incluem Apache Beam runners, como DataflowRunner e FlinkRunner. Pipeline options: "PipelineOptions" é uma parte essencial da arquitetura do Apache Beam que permite configurar a execução dos dados de forma eficiente, economizando tempo e esforço. Para ilustrar, imagine que você precise transportar várias caixas de um lugar para outro, mas precise decidir como empilhá-las em um caminhão. O PipelineOptions ajuda a tomar decisões importantes, como determinar o tamanho ideal do caminhão, quantas caixas podem ser empilhadas e como organizá-las para otimizar o espaço. As configurações podem incluir informações sobre o ambiente de execução, o tamanho do cluster de processamento, o tempo de retenção de dados em memória, entre outras opções. No exemplo acima, a classe MyCustomOptions é uma subclasse de PipelineOptions que define uma nova opção personalizada my_custom_option. O método _add_argparse_args adiciona a nova opção personalizada ao parser e define um valor padrão para ela. Em seguida, as opções personalizadas são visualizadas usando a função view_as do objeto beam_options, que retorna um objeto MyCustomOptions. O valor da opção personalizada é impresso na saída usando a variável my_custom_options. Este é apenas um exemplo simples de como criar uma opção personalizada e definir uma opção padrão usando a classe PipelineOptions. É possível definir opções personalizadas adicionais, dependendo das necessidades de pipeline. I/O: O Apache Beam I/O é uma ferramenta valiosa para a leitura e escrita de grandes volumes de dados, permitindo a utilização de um conjunto de bibliotecas, uma API única e um modelo de programação comum. Com o uso do Apache Beam I/O, os desenvolvedores podem processar dados de diversas fontes sem precisar conhecer as particularidades de cada uma delas. Ademais, o Apache Beam I/O oferece uma ampla variedade de conectores para diferentes fontes de dados, como Hadoop Distributed File System (HDFS), Amazon S3, Google Cloud Storage, BigQuery, Kafka, entre outras, além de suportar diversos formatos de dados, como CSV, JSON, Parquet, Avro, entre outros. Em resumo, o Apache Beam I/O é uma parte essencial do ecossistema do Apache Beam, que facilita para os desenvolvedores a tarefa de acessar e processar dados provenientes de várias fontes de entrada e saída de maneira simples e eficiente.
Arquitetura do Apache Beam content media
0
0
9
rodrigo.kartcheski
05 de abr. de 2023
In Big Data
E aí, galera irada! Vocês estão bem? Ao trabalharmos com engenharia de dados, é essencial dominarmos algumas linguagens que se tornam nossas ferramentas diárias. Nesse sentido, SQL e Python são linguagens complementares, assim como um time de futebol que possui zagueiros, meio-campo e atacantes, cada um com suas posições e funções específicas. Juntas, essas linguagens apresentam vantagens e desvantagens que, quando combinadas, são um diferencial. Diante desse contexto, decidi abordar as DEF funções reutilizáveis em Python, que, se utilizadas corretamente, podem aumentar significativamente a produtividade do desenvolvedor. O que são DEF? Em Python, existe uma palavra-chave muito importante chamada DEF. Essa palavra é usada para criar funções, que são blocos de código que fazem coisas específicas. Quando uma função é criada usando a palavra DEF em Python, um conjunto de instruções pode ser agrupado em um único bloco de código que pode ser usado várias vezes em um programa. Isso ajuda a deixar o código mais organizado e fácil de entender, além de permitir que as tarefas sejam reutilizadas em diferentes partes do programa. Em resumo, a palavra DEF é essencial para escrever código em Python de forma organizada e modular. No exemplo abaixo, a função criada se chama "saudacao" e tem um parâmetro chamado "nome". Quando a função é chamada passando o valor "Maria" como argumento, ela exibe a mensagem "Olá, Maria! Como você está?" na tela. Da mesma forma, quando a função é chamada passando o valor "João" como argumento, ela exibe a mensagem "Olá, João! Como você está?" na tela. Dessa forma, podemos reutilizar essa função em diferentes partes do programa, sem precisar repetir o mesmo bloco de código várias vezes. Qual é a sintaxe básica para definir DEF em Python? A sintaxe básica para definir uma função usando a palavra-chave DEF em Python: def: é a palavra-chave que indica que estamos definindo uma nova função. nome_da_funcao: é o nome que damos à função. Esse nome deve seguir as mesmas regras de nomenclatura de variáveis em Python (por exemplo, não pode começar com um número). parametro1, parametro2, ...: são os parâmetros da função. Eles são opcionais e podem ser usados para receber valores externos que a função vai usar para executar suas instruções. corpo da função: é o bloco de código que contém as instruções que a função executa quando é chamada. return resultado: é uma instrução opcional que especifica o valor que a função retorna quando é chamada. Se a função não precisar retornar nenhum valor, essa instrução pode ser omitida. Note que os parâmetros são opcionais e podem ser deixados de fora, assim como a instrução return. Porém, a palavra-chave DEF é sempre necessária para criar uma nova função. No exemplo abaixo criamos um dataframe com três colunas: id, nome, sobrenome: a função remover_caracteres_especiais usa a função regexp_replace para substituir qualquer caractere que não seja uma letra ou um número por uma string vazia. A função é aplicada às colunas "nome" e "sobrenome" do DataFrame usando a função withColumn. O resultado é um novo DataFrame com duas novas colunas, "nome_sem_caracteres" e "sobrenome_sem_caracteres", que contêm os valores das colunas originais com os caracteres especiais removidos. No exemplo abaixo, estamos passando um Dataframe declarado chamado df para a DEF colunas_para_maisculas(), com um parametro chamado colunas. O parâmetro "colunas" na assinatura da função "colunas_para_maiusculas" é uma lista de strings que especifica as colunas do dataframe que devem ser transformadas em maiúsculas. Na definição da função, o parâmetro "colunas" é definido com o tipo de dados "list", indicando que é esperada uma lista como entrada. O nome "colunas" é apenas uma convenção de nomenclatura para tornar o código mais legível. Dentro da função, a lista de colunas é percorrida em um loop for, e cada coluna é transformada em maiúscula usando a função "upper" do PySpark, que retorna uma nova coluna com os caracteres em maiúsculo. Em seguida, a coluna original é substituída pela nova coluna em maiúsculo no dataframe usando o método "withColumn". Quais são os diferentes tipos de parâmetros que podem ser usados em DEF? Existem três tipos de parâmetros que podem ser usados em funções DEF em Python. O primeiro tipo é o parâmetro posicional, que é obrigatório e deve ser passado na ordem em que é definido na função. Isso significa que se você tem uma função que recebe dois parâmetros posicionais, você deve passar o primeiro parâmetro primeiro e o segundo parâmetro em segundo lugar. O segundo tipo de parâmetro é o parâmetro com palavra-chave, que é opcional e tem um valor padrão. Esse tipo de parâmetro pode ser definido fora da ordem em que é definido na função, desde que o nome do parâmetro seja especificado. O terceiro tipo de parâmetro é o parâmetro de lista, que permite que uma função aceite um número variável de argumentos. Isso é útil quando você não sabe quantos argumentos serão passados para a função. Para definir um parâmetro de lista, você usa um asterisco (*) antes do nome do parâmetro e os argumentos são passados como uma lista. Parâmetros obrigatórios: esses são os parâmetros que devem ser passados para a função. Se você não fornecer um valor para esses parâmetros, a função produzirá um erro. Um exemplo de uma função que usa parâmetros obrigatórios é a seguinte: Neste exemplo, a função saudação tem um parâmetro obrigatório nome que deve ser fornecido ao chamar a função. Se você chamar a função sem fornecer um valor para nome, você receberá um erro. Parâmetros opcionais: esses são os parâmetros que não precisam ser passados para a função. Se nenhum valor for fornecido para esses parâmetros, a função usará um valor padrão. Um exemplo de uma função que usa parâmetros opcionais é a seguinte: Neste exemplo, a função somar tem dois parâmetros: x e y. O parâmetro y é opcional e tem um valor padrão de 0. Se você chamar a função sem fornecer um valor para y, a função usará o valor padrão de 0. Parâmetros nomeados: Nesse tipo de parâmetro, é possível definir um valor padrão para um parâmetro, tornando-o opcional na chamada da função. Esse tipo de parâmetro é útil quando se tem muitos argumentos opcionais na função, tornando a chamada mais clara e legível. Nesse exemplo, a função calcular_media recebe dois parâmetros obrigatórios (nota1 e nota2) e dois parâmetros opcionais (peso1 e peso2), que têm valores padrão definidos como 1. Na chamada da função, é passado um valor apenas para o parâmetro peso2, e o valor padrão é utilizado para peso1. Isso resulta em uma média ponderada com peso1=1 e peso2=2. Como definir parâmetros padrão em DEF? Para definir parâmetros padrão em uma definição de função usando o sinal de igual (=) depois do nome do parâmetro e, em seguida, o valor padrão que deseja atribuir a ele. Aqui está um exemplo simples: Neste exemplo, a função saudacao() tem dois parâmetros: nome e saudacao. O valor padrão para o parâmetro saudacao é "Olá". Se o valor do parâmetro saudacao não for especificado ao chamar a função, o valor padrão "Olá" será usado. Como podemos ver na imagem acima, podemos chamar a função saudacao() de várias maneiras diferentes. Como usar parâmetros nomeados em DEF? Em Python, você pode usar parâmetros nomeados (também conhecidos como argumentos nomeados) em uma definição de função para especificar explicitamente o valor de um parâmetro ao chamar a função, sem se importar com a ordem em que os parâmetros são declarados na definição da função. Para usar parâmetros nomeados em uma definição de função, você precisa incluir o nome do parâmetro seguido de um sinal de igual (=) e, em seguida, o valor que deseja atribuir a ele ao chamar a função. Aqui está um exemplo simples. Observe que, ao usar parâmetros nomeados, você não precisa se preocupar com a ordem em que os parâmetros são declarados na definição da função. Além disso, você pode misturar parâmetros nomeados e posicionais em uma chamada de função, mas é importante lembrar que todos os parâmetros posicionais devem vir antes dos parâmetros nomeados. Parametros de entrada e saida No seguinte exemplo, a e b são parâmetros de entrada da função "soma", mas não há um parâmetro de saída específico. O valor retornado pela função é um valor de saída que pode ser atribuído a uma variável, como você fez com a variável "c". Nesse caso, "c" é uma variável de saída que armazena o resultado da função. No entanto, ao chamar a função "soma", é necessario passar os argumentos "a" e "b". Caso contrario isso resultará em um erro, pois a função espera receber dois argumentos. Nesse exemplo, os valores de "a" e "b" são passados como argumentos ao chamar a função "soma", e o resultado é armazenado na variável "c" e impresso na tela. Para criar um exemplo que inclua um parâmetro de saída, podemos modificar a função "soma" para retornar tanto o resultado da soma quanto uma mensagem indicando que a operação foi realizada com sucesso. Assim: Nesse caso, a função "soma" retorna uma tupla contendo o resultado da soma e uma mensagem indicando que a operação foi realizada com sucesso. Em python a saída de uma DEF sempre será o valor de retorno de uma função (ou método) é especificado usando a instrução "return". Portanto, se você deseja que sua função retorne um valor específico, deve usar a instrução "return" dentro da função e especificar o valor que deseja retornar. Resumo Por hoje é isso pessoal, ficou extenso, mas o assunto é vasto. O texto acima explica o conceito de DEF em Python, que é a palavra-chave usada para criar funções que são blocos de código que executam tarefas específicas. As funções podem receber parâmetros e retornar valores. Elas ajudam a deixar o código mais organizado e modular, além de permitir a reutilização de tarefas em diferentes partes do programa. É possível definir funções em Python usando a sintaxe básica com a palavra-chave DEF, o nome da função, os parâmetros, o corpo da função e a instrução return, que é opcional. Um exemplo prático é dado com o uso da função para remover caracteres especiais em um DataFrame.
usando DEF em engenharia de dados content media
0
0
935
rodrigo.kartcheski
01 de abr. de 2023
In Big Data
Hoje gostaria de compartilhar com vocês uma situação que me deparei ao criar um fluxo de dados no Apache Beam. As condições de carga de dados devem ser cuidadosamente planejadas para evitar desperdício de recursos e, dependendo das regras de negócio, devem ser implementadas de uma ou de outra forma. Neste caso específico, eu estava lidando com UPSERT do Apache Beam para o Big Query. Fazer insert table é muito simples em qualquer tabela ou arquivo de dados. Porém, quando falamos de Big Data, envolvemos diferentes ferramentas e ambientes. Então, em muitos casos, fazer um update não é uma tarefa tão simples. Me deparei com um problema inusitado no Apache Beam, algo muito comum na vida de um engenheiro de dados: dados nulos. Dados nulos não são úteis para ninguém, mas nem sempre eles podem ser expurgados do processamento. Quando a regra de negócio exige que eles fiquem à disposição, é preciso tratá-los. Geralmente, prefiro usar valores default para datas, inteiros, strings e floats. Mas quando as regras de negócio exigem o contrário, podemos nos deparar com situações inusitadas. Uma dessas situações que me deparei foi ao fazer uma carga de dados através de um pipeline Beam para uma tabela do Big Query. Ao fazer o insert, não tive nenhum problema em subir campos com valores nulos. No entanto, ao fazer o primeiro update, os problemas começaram. Vasculhando daqui, vasculhando dali, as condições foram se ajeitando. Entretanto, nenhuma sintaxe conseguia resolver o problema de subir valores nulos em um update e por uma razão muito simples: Python trata valores nulos como None, que é um objeto único que é usado como o valor de retorno padrão para funções que não retornam um valor explícito. Já em SQL, o valor especial que indica a falta de um valor válido em uma coluna de uma tabela ou em uma expressão é NULL. Este era o problema que eu estava enfrentando. Por mais que tentasse, não conseguia fazer alterar os dados na tabela de destino. Tentei e tentei, mas nada. Foram diversas abordagens, algumas retornavam erro, outras nada, mas os dados desatualizados se mantinham firmes no Big Query. Felizmente, quando descobrimos que as sintaxes não são tão compatíveis como gostaríamos, começamos a pensar fora da caixa. Para encontrar a solução, descobri que existe uma fronteira fictícia em fluxo de dados, que é quando os dados cruzam a fronteira da sintaxe Py para a sintaxe SQL. Em algum momento, isso tem que acontecer, não é mesmo? Neste momento, os valores que são recebidos como None devem ser alterados para NULL antes de serem escritos no Big Query. Ao perceber esse padrão, foi fácil implementar um comando que alterasse os valores None para NULL e o problema foi resolvido. Desta forma, ao implementar a função de transformação no pipeline, adicionamos um comando que altera os valores None para NULL antes de escrevê-los no Big Query. Isso resolveu o problema de subir valores nulos em um update e os dados puderam ser atualizados corretamente na tabela de destino. Na imagem abaixo, podemos ver a função definida que trata o código e o comando de transformação que trata os valores no pipeline. Por padrão, todos os valores nulos são convertidos para None, mas com essa solução, agora podemos lidar adequadamente com valores nulos em um ambiente Big Data e garantir a integridade dos dados. Abaixo podemos ver o codigo executado na transformação, que percorre as linha retornando valores nulos para NULL para ser interpretado pelo SQL do Big Query. Desta forma conseguimos atualizar dados para NULL no Big Query usando o Apache Beam. Em resumo, o texto relata um problema encontrado ao fazer um UPSERT com o Apache Beam para o Big Query e como foi solucionado através da descoberta da fronteira fictícia em fluxo de dados. O problema em questão era que Python trata valores nulos como None, enquanto em SQL, o valor especial que indica a falta de um valor válido em uma coluna de uma tabela ou em uma expressão é NULL. Ao implementar um comando que alterasse os valores None para NULL antes de escrevê-los no Big Query, o problema foi resolvido e os dados puderam ser atualizados corretamente na tabela de destino. Essa solução possibilita lidar adequadamente com valores nulos em um ambiente Big Data e garantir a integridade dos dados.
Fazendo UPDATE de valores nulos no Big Query pelo Apache Beam content media
1
0
75
rodrigo.kartcheski
31 de mar. de 2023
In Big Data
A elaboração de um relatório de análise de falhas é de extrema importância, pois permite a realização de investigações minuciosas a fim de descobrir a causa raiz dos problemas e criar documentação que comprove a conformidade com normas e regulamentos. Dessa forma, é possível evitar a recorrência de incidentes e aumentar a conformidade e eficácia dos processos. Além disso, ao documentar os erros, a equipe pode aprender com eles, identificar tendências em problemas recorrentes e tomar medidas preventivas para reduzir custos e aumentar a confiabilidade dos sistemas, promovendo a transparência e responsabilidade com clientes, fornecedores e reguladores. Embora haja várias metodologias disponíveis para análise, não há uma única abordagem ideal para todos os cenários. Por exemplo, o diagrama de Ishikawa é frequentemente usado para identificar as possíveis causas raiz de um problema complexo, especialmente quando as causas potenciais não são óbvias e podem ser categorizadas em diferentes áreas, como pessoas, processos e equipamentos. Por outro lado, o método 5W2H é uma opção simples e eficaz para desenvolver um relatório de análise de dados. Esse método permite uma abordagem direta e organizada, seguindo sete perguntas fundamentais para estruturar a análise de forma clara e objetiva. O método 5W2H é uma técnica abrangente e útil para planejar, organizar e executar projetos e ações. Consiste em responder a sete perguntas-chave, sendo cinco iniciadas pela letra W (O que, Por que, Onde, Quando e Quem) e duas pela letra H (Como e Quanto). A seguir, uma breve explicação sobre cada uma das perguntas: Who (quem): Essa pergunta busca entender quem são as pessoas responsáveis por realizar as tarefas e alcançar os objetivos da analise. É importante definir quem são as pessoas envolvidas na analise e quais são suas funções e responsabilidades. What (o que): Essa pergunta busca entender qual é a dimensão do problema e consequentemente a tarefa ou problema que precisa ser resolvido. Ela é importante para identificar a natureza da ação e qual é o objetivo principal. Where (onde): Essa pergunta busca entender onde a ação será realizada. É importante definir o local onde as tarefas serão executadas para garantir a disponibilidade dos recursos necessários e evitar desperdícios. Why (por que): Essa pergunta procura entender a razão ou justificativa para a realização da tarefa ou para solucionar o problema. Ela ajuda a compreender a importância da ação, e quais benefícios serão obtidos. When (quando): Essa pergunta busca entender quando a ação de correção deve ser realizada. É importante definir uma data para o início e para o fim da ação ou se a tarefa foi concluída durante a analise deve ter este apontamento, assim como para as tarefas que fazem parte dele. How (como): Essa pergunta busca entender como as tarefas serão realizadas e como serão alcançados os objetivos. É importante definir os processos, as técnicas e as ferramentas necessárias para executar as tarefas e alcançar os objetivos. How much (quanto): Essa pergunta busca entender qual é o custo envolvido na realização das tarefas. É importante definir o orçamento disponível para o projeto e para cada tarefa, a fim de evitar desperdícios e garantir a viabilidade financeira do projeto. Embora possa parecer complexo à primeira vista, o método 5W2H é extremamente útil, que pode ser escrito em uma pagina, mas de grande ajuda para desenvolver o raciocínio diante de um problema. Ao seguir as perguntas, é possível identificar qual profissional está analisando o problema, compreender a sua dimensão, localização, tempo de ocorrência, motivo e forma como ocorreu. A primeira pergunta é crucial para compreendermos quem foi o profissional responsável pela análise. As perguntas 2 e 3, quando combinadas, permitem uma descrição precisa do ocorrido, ou seja, do passado, bem como onde o problema aconteceu e onde será solucionado. Já a quarta pergunta deve explicar por que e como o problema surgiu, incluindo informações relevantes obtidas na investigação analítica, bem como as conclusões e observações do analista. As perguntas 5 e 6, devem responder às perguntas 2, 3 e 4, indicando cronograma e quais ações precisam ser tomadas para solucionar o problema. A pergunta 5 se concentra em fornecer uma estimativa de tempo para solução do problema, enquanto a pergunta 6 se concentra em identificar as atividades necessárias para resolver o problema. A pergunta número 7 nem sempre é aplicável, já que na maioria das vezes os custos envolvidos são baixos (embora sempre existam custos), o que pode torná-la desnecessária de ser abordada em termos justificativos. Caso necessário, pode-se adicionar um tópico para resultados, resumindo em até três frases as principais conclusões obtidas a partir das respostas às perguntas anteriores. Obviamente, se o relator do relatório desejar ser mais detalhista ele pode usar gráficos usar figuras imagens enfim pode incrementar o relatório da forma que achar que precisa, sempre tendo o cuidado de não fugir da essência. O documento pode ser escrito em formato de titulo no word ou Markdown. Como mencionamos anteriormente, a elaboração de um relatório de análise de falhas é crucial para identificar a causa raiz dos problemas e prevenir a recorrência de incidentes. Dentre as diversas metodologias disponíveis para análise, destaca-se a 5W2H, que é abrangente, simples e pode ser aplicada por qualquer pessoa, independentemente da área de atuação. A metodologia consiste em responder a sete perguntas-chave, o que facilita a comunicação e a solução de problemas em equipe. Seguindo essas perguntas, é possível identificar o responsável pela análise, compreender a dimensão e a localização do problema, explicar por que e como o problema surgiu, definir um cronograma, um orçamento e as ações necessárias para solucionar o problema. O uso dessa metodologia permite uma abordagem direta e organizada na análise de falhas e é uma ferramenta importante para aumentar a conformidade e a eficácia dos processos.
Como fazer um relatório de falhas com 5W2H content media
2
1
223
rodrigo.kartcheski
31 de mar. de 2023
In Big Data
O que é o GIT A escrita tem sido uma forma de comunicação presente na vida humana desde tempos imemoriais. As primeiras formas de escrita surgiram em torno de 4000 a.C., e desde então a humanidade evoluiu as técnicas desta forma de comunicação. As primeiras formas de escrita foram em tábuas de argila e papiro, respectivamente. Os pergaminhos criados pelos antigos egípcios por volta do século III a.C. foram amplamente utilizados até a invenção do papel pelos chineses no século II a.C. Posteriormente, outras invenções importantes surgiram, como a impressora, o telégrafo e o computador. Recentemente, a internet e a tecnologia digital têm sido as grandes inovações que revolucionaram a comunicação escrita, permitindo a criação de novas formas de comunicação, como o e-mail, as redes sociais, os aplicativos de mensagens e outros meios de comunicação em tempo real. Essas inovações tornaram a comunicação mais rápida, acessível e globalizada do que nunca antes. Com o progresso da tecnologia, tornou-se necessário criar novas linguagens artificiais para simplificar a comunicação entre humanos e máquinas. Isso resultou em um aumento no desenvolvimento de código para atender a essa demanda e, consequentemente, a qualidade do código passou a ser cada vez mais exigida. A necessidade de controle e entrega também se tornou evidente, o que levou ao surgimento da ideia de versionar o código. Foi então que surgiu o Git, uma plataforma que possibilita o controle de versionamento de códigos. O Git é um software que funciona como um sistema de gerenciamento de versões distribuído. Foi criado por Linus Torvalds com o objetivo inicial de solucionar os problemas de versionamento de código no desenvolvimento do kernel Linux, permitindo o registro do histórico de edições de diferentes tipos de arquivos. O sucesso do software foi tão grande que ele se tornou amplamente utilizado por muitos outros projetos ao longo do tempo. Porque usar o GIT Há várias razões pelas quais o Git é amplamente adotado como um sistema de controle de versão de código. Alguns dos principais motivos incluem: Sistema de controle de versão distribuído: Ao contrário de outros sistemas de controle de versão centralizados, o Git é distribuído, o que significa que cada desenvolvedor tem uma cópia completa do repositório. Isso torna o processo de colaboração mais fácil e flexível, permitindo que os desenvolvedores trabalhem em diferentes ramos do projeto simultaneamente. Histórico completo de alterações: O Git mantém um registro de todas as alterações feitas no código-fonte, permitindo que os desenvolvedores acessem o histórico completo de alterações. Isso ajuda a evitar a perda de código e facilita a resolução de problemas. Ferramentas de colaboração: O Git oferece várias ferramentas para facilitar a colaboração entre desenvolvedores, incluindo a capacidade de revisar e mesclar o código-fonte de diferentes desenvolvedores. Gerenciamento de conflitos: O Git possui recursos para ajudar a gerenciar conflitos quando duas ou mais pessoas modificam o mesmo código-fonte ao mesmo tempo. Ramificação e fusão de código: O Git permite que os desenvolvedores criem diferentes ramificações do projeto, o que é útil para testar novos recursos ou corrigir problemas sem afetar o código-fonte principal. Em seguida, é possível mesclar as alterações de volta à ramificação principal de forma organizada e controlada. Popularidade e suporte: O Git é amplamente utilizado em todo o mundo e possui uma grande comunidade de usuários e desenvolvedores, o que significa que existem muitos recursos, tutoriais e fóruns disponíveis para ajudar a resolver problemas ou aprender a usar o sistema. Databricks Como uma possível forma de melhor utilizar o Git no Databricks, é recomendado seguir algumas boas práticas. É importante utilizar pelo menos três branches: a branch pessoal, a branch de desenvolvimento e a branch de produção. Na branch pessoal, somente um desenvolvedor deve acessar e desenvolver o código. Na branch de desenvolvimento, o desenvolvedor deve fazer um merge do notebook quando acreditar que o código está maduro, compartilhando desta forma com outros desenvolvedores. Já a branch de produção é para elevar somente notebooks finalizados, testados e homologados. Entre a branch de desenvolvimento e produção podem ser implantadas outras branches como a de homologação por exemplo. Ao criar a branch pessoal, é recomendado fazer o pull da branch de desenvolvimento, considerando-a como a branch centralizadora, pois esta branch é a menos regulamentada e a mais adequada para receber as alterações feitas pelos desenvolvedores. É importante que todos da equipe estejam cientes deste procedimento. Dessa forma, garante-se que o recurso baixado está correto e sem falhas, já que iniciar uma edição a partir de um arquivo com falhas ou que esteja sendo editado em outra frente pode gerar conflitos. No entanto, algumas equipes podem optar por fazer o pull diretamente da branch de produção em vez da branch de desenvolvimento. Quem ainda não conhece sobre GIT está se perguntando o que é “Pull Request” ou simplesmente “pull”. Responder a esta pergunta envolve o entendimento de duas palavrinhas que vão acompanhar os entusiastas para sempre: “pull” e “push”. Estas duas podem causar certa confusão se não forem bem entendidas. O contrário de "pull" no Git é "push". Enquanto "pull" é usado para trazer as alterações feitas por outros colaboradores em um repositório remoto para o repositório local, "push" é usado para enviar as alterações feitas no repositório local para um repositório remoto. O comando "git push" é usado para enviar as alterações para um repositório remoto específico, como o GitHub, GitLab ou Bitbucket. Isso pode ficar um pouco confuso para quem usa Databricks, pois o comando “push” não existe neste Software, aqui existe apenas o comando “pull”. Isto quer dizer que só é possível “puxar, ou, trazer” os arquivos de código para a branch, e não empurrá-los para o repositório central. Então como podemos “empurrar” uma branch de códigos atualizados para o repositório de destino? Usando o comando commit. No Git, um commit é uma gravação de uma alteração em um ou mais arquivos do seu repositório, contendo um conjunto de mudanças e uma mensagem descritiva. Cada commit é um registro único que representa uma versão do seu projeto, com um identificador único chamado hash do commit. Ao executar o comando commit no Databricks uma versão é gravada no gerenciador de código-fonte (Bitbucket ou Github por exemplo), a partir daí é possível fazer o “Pull Resquest” da Branch de desenvolvimento para a branch de produção por exemplo. Até agora não falamos sobre “push”. No entanto, embora a função “push” não esteja disponível para desenvolvedores do Databricks usarem diretamente, é importante ter em mente seu uso, pois em outras ocasiões o comando será útil. É importante saber que o “pull” atende às necessidades da área de data analytics. Após a finalização de todos os commits no Databricks e a abertura do site gerenciador de código-fonte (Bitbucket ou Github), é necessário fazer um “pull” da branch “pessoal” para a branch de desenvolvimento (para atualizar) ou desta para a branch de produção, a fim de efetuar a atualização da branch de destino. Por outro lado, é importante estar ciente de que não é possível “empurrar” os arquivos atualizados no gerenciador de código-fonte para o Databricks. Portanto, é necessário fazer sempre um “pull” do repositório central (gerenciador de código-fonte) para o repositório local (Databricks) quando se inicia um novo desenvolvimento no Databricks. Isso deve ser seguido como um hábito. As branches são criadas no repositório central (gerenciador de código-fonte, por exemplo) e, em seguida, copiadas para o Databricks. Isso garante que os códigos do repositório possam ser recuperados em casos de catástrofes. No entanto, em alguns casos, essa regra pode não ser tão rigorosa em termos de segurança, permitindo que um arquivo seja editado simultaneamente localmente e na branch de produção. A falta de atenção nesta questão é um perigo. Cuidados Entender e utilizar os comandos "commit", "pull", aprovar e merge é fundamental para o desenvolvimento de projetos em equipe ou individual. É importante lembrar que fazer uma alteração na branch de produção, por menor que seja, mesmo que seja para "verificar um comportamento", é inadmissível, pois pode causar problemas graves sejam técnicos ou comerciais. Portanto, é crucial criar uma branch para fazer as alterações necessárias e, em seguida, deletá-la. Isso pode parecer um trabalho insignificante, mas é essencial para garantir a integridade do código. Não há necessidade de ter medo de deletar uma branch pessoal criada para uso temporário, pois ela não será mais utilizada. É recomendado deletá-la ao final do desenvolvimento, pois manter branches pessoais em desuso no repositório pode poluir o ambiente. Ao seguir essas práticas, é possível garantir um ambiente de desenvolvimento mais organizado e seguro para toda a equipe. Ao trabalhar com branches no Databricks é importante conhecer as opções de resolver conflitos de merge. Mas o que são conflitos de merge? Sabemos que ao desenvolver um código fazemos diversos commits dentro de uma branch e ao finalizar o desenvolvimento criamos um “pull”. Pull request é uma forma de solicitar a revisão e aprovação do código por outros membros da equipe, e que essa é uma prática comum em projetos colaborativos. Para garantir a alta qualidade do código, o “pull request” precisa ser aprovado, isto é, neste momento a qualidade do código pode ser avaliada, e se aprovado, deve ser feito um merge. Um "merge" é o processo de combinar duas ou mais ramificações (branches) de forma a integrar alterações feitas em diferentes branches do mesmo repositório e manter um histórico único e ordenado de todas as alterações de um repositório Git em uma única ramificação, isto é, o merge unifica os arquivos recém elevados, e até então instáveis, da branch de origem com os arquivos estáveis da branch de destino. Antes de seguir na leitura volte ao paragrafo anterior e observe a importância de não fazer alteração diretamente na branch de produção. É importante usar as branches de desenvolvimento, e não fazer alterações diretas na branch de produção, pois isso pode gerar conflitos e dificultar o trabalho da equipe. E os conflitos? Os conflitos ocorrem ao clicar no comando “merge”. A explicação é que toda branch inicia de uma ramificação principal. Ao desenvolver uma nova funcionalidade em uma ramificação chamada "feature" por exemplo, o desenvolvedor pode querer mesclar essa funcionalidade de volta na ramificação principal do repositório (geralmente chamada de "master" ou "main"). Dependendo do caso, o Git pode realizar a operação automaticamente, ou pode precisar que o desenvolvedor resolva conflitos manualmente, caso haja alterações conflitantes nas duas ramificações. Conflito de merge é um problema que pode ocorrer ao mesclar (ou "fundir") duas versões diferentes de um mesmo arquivo ou conjunto de arquivos em um sistema de controle de versão, como o Git. Isso pode acontecer quando duas pessoas estão trabalhando no mesmo arquivo ao mesmo tempo e fazem alterações diferentes em áreas próximas ou na mesma linha do código. Ao tentar mesclar essas alterações, o sistema pode não saber como combiná-las, resultando em um conflito que precisa ser resolvido manualmente pelos usuários envolvidos. A resolução de conflitos de merge é uma parte crítica do trabalho em equipe em projetos de desenvolvimento de software e requer comunicação e colaboração para garantir que as mudanças sejam mescladas de forma eficiente e sem erros. Resolver conflitos de merge pode ser considerado como o arroz com feijão do desenvolvedor do Databricks, pois acontece com bastante frequencia, mas não é para se desesperar. Com pouco de tempo se ganha experiencia para que a resolução dos conflitos deixe de ser uma preocupação e flua suavemente. Para resolver conflitos é importante conhecer as opções que o Git oferece e as opções que o gerenciador de código-fonte (Bitbucket ou Github por exemplo) oferecem. Há algumas boas práticas para nomear branches em repositórios de código que podem ajudar a manter a organização e a clareza. É importante usar nomes descritivos que deixem claro o que está sendo trabalhado, como "feature/login" para uma nova funcionalidade de login. Letras minúsculas e hífens são frequentemente usados para separar palavras em nomes de branches, tornando-os mais legíveis e menos propensos a erros. É fundamental manter a mesma convenção de nomenclatura em todo o projeto, por exemplo, usando o prefixo "feature/" para todas as branches de novas funcionalidades. O nome do branch deve ser o mais curto possível, mas ainda assim descritivo. É recomendado evitar caracteres especiais que possam causar problemas em alguns sistemas de controle de versão. Se trabalhando em um projeto em equipe, incluir o número do ticket correspondente pode ser útil, como em "feature/login-123". Vale lembrar que a nomenclatura do branch é uma questão de preferência pessoal e convenções da equipe, mas é importante manter uma convenção clara e consistente para facilitar a compreensão e a organização do repositório de código. Existem vários prefixos comuns que podem ser usados para ajudar a identificar o tipo de branch em um repositório de código. Alguns exemplos incluem: "feature/" ou "feat/", usado para branches que contêm novas funcionalidades que estão sendo desenvolvidas; "bugfix/" ou "fix/": usado para branches que contêm correções de bugs; "hotfix/" ou "hf/", usado para branches que contêm correções urgentes que precisam ser implantadas rapidamente; "release/" ou "rel/", usado para branches que contêm código que está pronto para ser implantado em produção; "develop/" ou "dev/", usado para a branch principal de desenvolvimento, onde todo o trabalho está integrado antes de ser mesclado em um branch de release ou main/master; "main/", "master/", ou "trunk/, usado para a branch principal de desenvolvimento, que contém o código estável e pronto para produção. É essencial ter em mente que a escolha do prefixo para a nomenclatura do branch é uma decisão que depende da preferência pessoal e da convenção adotada pela equipe. Contudo, é crucial manter a consistência na forma como os nomes dos branches são definidos em todo o repositório de código, a fim de facilitar a compreensão e organização do projeto. Resumo O uso do Git como ferramenta de versionamento traz muitos benefícios para qualquer tipo de projeto, inclusive no Databricks, garantindo a qualidade do código. A curva de aprendizado para começar a usar o Git como ferramenta de versionamento é relativamente baixa diante dos benefícios. É necessário ter a mente aberta quanto às nomenclaturas e padrões, pois cada equipe pode adaptá-los conforme a necessidade de adequação ao projeto, mas é importante não fugir das boas práticas citadas nos livros sobre Git e nas recomendações internacionais. Além de entender como o commit funciona em relação à branch pessoal e como esta se relaciona com as outras branches, é fundamental entender a hierarquia das branches e os comandos "pull", "push", "approve" e merge. E, sobretudo, é importante ter em mente que nunca se deve alterar o código diretamente na branch master. Da mesma forma, que entender os comandos principais, é preciso conhecer as formas que o Git e as ferramentas de gerenciamento de código-fonte disponibilizam para resolver problemas de conflito de merge. Assimilando o básico do Git, é possível aumentar a confiabilidade dos códigos entregues, ter mais eficiência e qualidade no trabalho.
Como usar o GIT no Databricks content media
1
0
36
rodrigo.kartcheski
31 de mar. de 2023
In Big Data
Análise de negócios e análise de requisitos estão entre as atividades mais importantes do processo de engenharia de dados. A lógica é simples; todo trabalho da engenharia de dados nasce para atender uma necessidade de negócio, e para atender tais necessidades é necessário consumir regras de negócio. Como as regras de negócio não podem ser consumidas diretamente, são necessários definir requisitos que compreendam tais regras. A regra de negócio continua existindo mesmo que não exista um sistema para automatizá-la, ela vem antes do requisito, ela mantém a lógica do negócio repetível, ou seja, é possível fazer de novo de forma que aconteça sempre o mesmo resultado e que seja possível tomar uma decisão baseada na regra. Por exemplo: o açaí deve ser entregue aos clientes sempre gelado de forma que proporcione sensação de frescor, após aberto deve ser consumido no mesmo dia. Os requisitos devem ser criados para atender regras de negócio. Por exemplo: o açaí deve se manter na temperatura controlada de X graus, após aberto o sistema deve dar baixa na unidade do pacote, não permitindo que seja lido duas vezes o mesmo código do produto. Desta forma, para a área de engenharia de dados, a regra de negócio é importante para explicar o objetivo do desenvolvimento de um pipeline de processamento de dados. No entanto existe um obstáculo no meio do caminho entre a regra de negócio e a entrega de uma tabela que podemos chamar de “conversão útil”. Durante o processo de passagem de conhecimento da regra de negócio em “código” é preciso discernir muitas questões, como por exemplo, o próprio entendimento do que é regra de negócio e requisito. Para melhorar a experiência da conversão entra em campo o profissional de requisitos. Para um bom levantamento de requisitos é preciso ter conhecimento de algumas técnicas como técnicas de entrevistas para cobrir o maior número de perguntas possíveis sobre o objetivo da entrevista, anotações eficientes, conhecimento em UX, análise de negócios, ter alguns livros na prateleira como “O Teste da Mãe: Como conversar com clientes e descobrir se sua ideia é boa, mesmo com todos mentindo para você” e “Metodologia e Engenharia de Requisitos para projetos de Business Intelligence”. O UX une humanidade e a regra de negócio sempre refletindo como os dados podem agregar na vida do cliente, para isso utiliza técnicas que lhe ajudam a aprofundar-se nos sentimentos do usuário que é uma etapa importante, difícil de se dimensionar e automatizar. O Analista de Negócio busca entender os processos de negócio e identificar as opções para melhoria do negócio com uso de TI. Entre as técnicas de anotações eficientes podemos citar anotações de tópicos, método cornell, mapa mental, método do fluxo. No método de anotações de tópicos deve-se anotar as informações em tópicos, sem se preocupar com os detalhes. No método cornell, divide-se uma folha em três partes: ideias principais, notas e sumário. Esta técnica pode ser usada para resumir algum conteúdo, anotar as palavras chave e fazer um sumário do assunto. No mapa mental, utiliza-se uma folha em branco para colocar o assunto principal no meio dela e depois criar ramificações de assuntos. No método do fluxo somente quem faz a anotação vai entender mas se pode escrever livremente, da forma que se ouve sem se preocupar com padrões de escritas. A Álgebra Relacional é um conjunto de operações sobre modelos relacionais de dados. Seguir a simbologia da linguagem pode ser um processo moroso e técnico, mas seguir o conceito proporciona algumas vantagens sobre outras abordagens. A álgebra relacional tem origem na matemática, portanto é mais fácil de explicar a um usuário a compreensão dos conjuntos, permitindo uma comunicação franca com os usuários de negócio, e uma oportunidade de manter comunicação neutra pelo fato de não ser necessário adentrar a conceitos de linguagens artificiais, como SQL por exemplo. Na maioria dos casos o uso da álgebra relacional vem do fato de que é necessário combinar mais de um conjunto de dados para gerar informação, e cada combinação gera um novo conjunto de dados. Há seis operações fundamentais na álgebra relacional: Seleção, Projeção, Produto cartesiano, União, Diferença entre conjuntos e Renomear. Estas operações são indispensáveis, sem elas dificilmente será possível avançar no desenvolvimento do código. Por último, mas não menos importante, vamos falar de análise de negócio, que segue o IIBA, regido pelo livro chamado BABOK. O Analista de Negócios é responsável por entender os processos de negócio e identificar as opções para melhoria do negócio com o uso de TI, em outras palavras, podemos dizer que o analista de negócio deve entender a dor do cliente e procurar uma solução a melhor solução a nível de negócio. À medida que o analista de requisitos se empodera dos conhecimentos citados acima ele vai se tornando mais assertivo nas informações e capaz de criar soluções impactantes do ponto de vista dos stakeholders. Obviamente o caminho não é curto, mas com uma trilha é possível alcançar índices satisfatórios em cada área dentro de um tempo aceitável.
1
0
75

rodrigo.kartcheski

Mais ações
bottom of page