

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Três tipos de trabalho de ETL do AWS Glue para converter dados em Apache Parquet
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet"></a>

*Adnan Alvee, Nith Govindasivan e Karthikeyan Ramachandran, Amazon Web Services*

## Resumo
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-summary"></a>

Na nuvem da Amazon Web Services (AWS), o AWS Glue é um serviço para extração, transformação e carregamento (ETL) totalmente gerenciado. O AWS Glue torna econômico categorizar os dados, limpá-los, aprimorá-los e movê-los de modo confiável entre vários armazenamentos e fluxos de dados.

Esse padrão fornece diferentes tipos de trabalho no AWS Glue e usa três scripts diferentes para demonstrar a criação de trabalhos de ETL.

Você pode usar o AWS Glue para escrever trabalhos de ETL em um ambiente de shell Python. Você também pode criar trabalhos ETL em lote e de streaming usando Python PySpark () ou Scala em um ambiente gerenciado do Apache Spark. Para começar a criar trabalhos de ETL, esse padrão se concentra em trabalhos ETL em lote usando Python, shell e Scala. PySpark Os trabalhos de shell do Python são destinados a workloads que exigem menor poder computacional. O ambiente gerenciado do Apache Spark é destinado a workloads que exigem alto poder computacional.

O Apache Parquet foi desenvolvido para dar suporte a esquemas eficientes de compressão e codificação. Ele pode acelerar suas workloads de análise porque armazena dados de forma colunar. A conversão de dados em Parquet pode economizar espaço de armazenamento, custo e tempo no longo prazo. Para saber mais sobre o Parquet, consulte a postagem do blog [Apache Parquet: Como ser um herói com o formato de dados colunares de código aberto](https://blog.openbridge.com/how-to-be-a-hero-with-powerful-parquet-google-and-amazon-f2ae0f35ee04).

## Pré-requisitos e limitações
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-prereqs"></a>

**Pré-requisitos **
+ Perfil do AWS Identity and Access Management (IAM) (se você ainda não tiver um perfil, consulte a seção [Informações adicionais](#three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-additional).)

## Arquitetura
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-architecture"></a>

**Pilha de tecnologias de destino**
+ AWS Glue
+ Amazon Simple Storage Service (Amazon S3)
+ Apache Parquet

**Automação e escala**
+ Os [fluxos de trabalho do AWS Glue](https://docs.aws.amazon.com/glue/latest/dg/workflows_overview.html) oferecem suporte à automação total de um pipeline de ETL.
+ Você pode alterar o número de unidades de processamento de dados (DPUs) ou tipos de trabalhadores para escalar horizontal e verticalmente.

## Ferramentas
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-tools"></a>

**Serviços da AWS**
+ O [Amazon Simple Storage Service (Amazon S3)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) é um serviço de armazenamento de objetos baseado na nuvem que ajuda você a armazenar, proteger e recuperar qualquer quantidade de dados.
+ O [AWS Glue](https://docs.aws.amazon.com/glue/latest/dg/what-is-glue.html) é um serviço de ETL totalmente gerenciado para categorizar, limpar, enriquecer e mover dados entre armazenamentos de dados e fluxos de dados.

**Outras ferramentas**
+ O [Apache Parquet](https://parquet.apache.org/) é um formato de arquivos de dados orientados por colunas de código aberto projetado para armazenamento e recuperação.

**Configuração**

Use os dados a seguir para configurar a potência computacional do AWS Glue ETL. Para reduzir custos, use as configurações mínimas ao executar a workload fornecida nesse padrão. 
+ **Python shell**: você pode usar 1 DPU para utilizar 16 GB de memória ou 0,0625 DPU para utilizar 1 GB de memória. Esse padrão usa 0,0625 DPU, que é o padrão no console do AWS Glue.
+ **Python ou Scala para Spark**: se você escolher os tipos de trabalho relacionados ao Spark no console, o AWS Glue, por padrão, usa 10 operadores e o tipo de operador G.1X. Esse padrão usa dois operadores, que é o número mínimo permitido, com o tipo de operador padrão, que é suficiente e econômico.

A tabela a seguir mostra os diferentes tipos de operadores do AWS Glue para o ambiente Apache Spark. Como um trabalho de Python shell não usa o ambiente Apache Spark para executar o Python, ele não está incluído na tabela.


| 
| 
|  | Standard | G.1X | G.2X | 
| --- |--- |--- |--- |
| vCPU | 4 | 4 | 8 | 
| Memória | 16 GB | 16 GB | 32 GB | 
| Espaço em disco | 50 GB | 64 GB | 128 GB | 
| Executor por operador | 2 | 1  | 1 | 

**Código **

Para ver o código usado nesse padrão, incluindo o perfil do IAM e a configuração de parâmetros, consulte a seção [Informações adicionais](#three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-additional).

## Épicos
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-epics"></a>

### Carregar os dados
<a name="upload-the-data"></a>


| Tarefa | Description | Habilidades necessárias | 
| --- | --- | --- | 
| Carregar dados para um bucket do S3 novo ou existente. | Crie ou use um bucket do S3 existente na sua conta. Faça upload do arquivo sample\_data.csv na seção [Anexos](#attachments-8c926709-8fa4-417f-9aaf-bcc8113d018f) e anote a localização do bucket e do prefixo do S3. | AWS geral | 

### Criar e executar o trabalho do AWS Glue
<a name="create-and-run-the-aws-glue-job"></a>


| Tarefa | Description | Habilidades necessárias | 
| --- | --- | --- | 
| Criar o trabalho do AWS Glue. | Na seção ETL do console do AWS Glue, adicione uma tarefa do AWS Glue. Selecione o tipo de trabalho apropriado, a versão do AWS Glue e o DPU/Worker tipo e número de trabalhadores correspondentes. Consulte a seção *Configuração* para obter detalhes. | Desenvolvedor, nuvem ou dados | 
| Alterar os locais de entrada e saída. | Copie o código correspondente ao seu trabalho do AWS Glue e altere o local de entrada e saída que você anotou no épico **Upload dos dados**. | Desenvolvedor, nuvem ou dados | 
| Configurar os parâmetros. | Você pode usar os trechos fornecidos na seção [Informações adicionais](#three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-additional) para definir parâmetros para seu trabalho de ETL. O AWS Glue usa quatro nomes de argumentos internamente:[See the AWS documentation website for more details](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/patterns/three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet.html)<br />O parâmetro `--JOB_NAME` deve ser inserido explicitamente no console do AWS Glue. Escolha **Trabalhos**, **Editar trabalho**, **Configuração de segurança, bibliotecas de scripts e parâmetros do trabalho (opcional)**. Insira `--JOB_NAME` como chave e forneça um valor. Você também pode usar a AWS Command Line Interface (AWS CLI) da AWS ou a API do AWS Glue para definir esse parâmetro. O parâmetro `--JOB_NAME` é usado pelo Spark e não é necessário em um trabalho do ambiente shell do Python.<br />Você deve adicionar `--` antes de cada nome de parâmetro; caso contrário, o código não funcionará. Por exemplo, para os trechos de código, os parâmetros de localização devem ser invocados por `--input_loc` e `--output_loc`. | Desenvolvedor, nuvem ou dados | 
| Executar o trabalho de ETL. | Execute seu trabalho e verifique a saída. Observe quanto espaço foi reduzido em relação ao arquivo original. | Desenvolvedor, nuvem ou dados | 

## Recursos relacionados
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-resources"></a>

**Referências**
+ [Apache Spark](https://spark.apache.org/)
+ [AWS Glue: como funciona](https://docs.aws.amazon.com/glue/latest/dg/how-it-works.html)
+ [Preços do AWS Glue](https://aws.amazon.com/glue/pricing/)

**Tutoriais e vídeos**
+ [O que é o AWS Glue?](https://www.youtube.com/watch?v=qgWMfNSN9f4)

## Mais informações
<a name="three-aws-glue-etl-job-types-for-converting-data-to-apache-parquet-additional"></a>

**Perfil do IAM**

Ao criar os trabalhos do AWS Glue, você pode usar um perfil existente do IAM que tenha as permissões mostradas no seguinte trecho de código ou uma nova função.

Use o seguinte código YAML para criar um novo perfil.

```
# (c) 2022 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This AWS Content is provided subject to the terms of the AWS Customer
# Agreement available at https://aws.amazon.com/agreement/ or other written agreement between Customer and Amazon Web Services, Inc.

AWSTemplateFormatVersion: "2010-09-09"

Description: This template will setup IAM role for AWS Glue service.

Resources:
  rGlueRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "glue.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-s3-limited-read-write-inline-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "s3:PutObject"
                  - "s3:GetObject"
                Resource: "arn:aws:s3:::*/*"
      Tags:
        - Key  : "Name"
          Value : !Sub "${AWS::StackName}"

Outputs:
  oGlueRoleName:
    Description: AWS Glue IAM role
    Value:
      Ref: rGlueRole
    Export:
      Name: !Join [ ":", [ !Ref "AWS::StackName", rGlueRole ] ]
```

**Python shell do AWS Glue**

O código Python usa os Pandas e as PyArrow bibliotecas para converter dados em Parquet. A biblioteca Pandas já está disponível. A PyArrow biblioteca é baixada quando você executa o padrão, porque é uma execução única. Você pode usar arquivos de roda PyArrow para converter em uma biblioteca e fornecer o arquivo como um pacote de biblioteca. Para obter mais informações sobre empacotamento de arquivos wheel, consulte [Fornecer sua própria biblioteca Python](https://docs.aws.amazon.com/glue/latest/dg/add-job-python.html).

*Parâmetros do Python shell do AWS Glue*

```
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["input_loc", "output_loc"])
```

*Código do Python shell do AWS Glue*

```
from io import BytesIO
import pandas as pd
import boto3
import os
import io
import site
from importlib import reload
from setuptools.command import easy_install
install_path = os.environ['GLUE_INSTALLATION']
easy_install.main( ["--install-dir", install_path, "pyarrow"] )
reload(site)
import pyarrow


input_loc = "s3://bucket-name/prefix/sample_data.csv"
output_loc = "s3://bucket-name/prefix/"


input_bucket = input_loc.split('/', 1)[0]
object_key = input_loc.split('/', 1)[1]


output_loc_bucket = output_loc.split('/', 1)[0]
output_loc_prefix = output_loc.split('/', 1)[1] 


s3 = boto3.client('s3')
obj = s3.get_object(Bucket=input_bucket, Key=object_key)
df = pd.read_csv(io.BytesIO(obj['Body'].read()))


parquet_buffer = BytesIO()
s3_resource = boto3.resource('s3')
df.to_parquet(parquet_buffer, index=False) 
s3_resource.Object(output_loc_bucket, output_loc_prefix +  'data' + '.parquet').put(Body=parquet_buffer.getvalue())
```

**Trabalho do AWS Glue Spark com Python**

Para usar um tipo de trabalho do AWS Glue Spark com Python, escolha **Spark** como tipo de trabalho. Escolha o **Spark 3.1, Python 3 com melhor tempo de startup do trabalho (Glue versão 3.0)** como a versão do AWS Glue.

*Parâmetros do Python do AWS Glue*

```
from awsglue.utils import getResolvedOptions

args = getResolvedOptions(sys.argv, ["JOB_NAME", "input_loc", "output_loc"])
```

*Trabalho do AWS Glue Spark com código Python*

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.transforms import *
from awsglue.dynamicframe import DynamicFrame
from awsglue.utils import getResolvedOptions
from awsglue.job import Job


sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)

input_loc = "s3://bucket-name/prefix/sample_data.csv"
output_loc = "s3://bucket-name/prefix/"

inputDyf = glueContext.create_dynamic_frame_from_options(\
    connection_type = "s3", \
    connection_options = { 
        "paths": [input_loc]}, \
    format = "csv",
    format_options={
        "withHeader": True,
        "separator": ","
    })


outputDF = glueContext.write_dynamic_frame.from_options(\
    frame = inputDyf, \
    connection_type = "s3", \
    connection_options = {"path": output_loc \
        }, format = "parquet")
```

Para um grande número de arquivos grandes compactados (por exemplo, 1.000 arquivos com cerca de 3 MB cada), use o parâmetro `compressionType` com o parâmetro `recurse` para ler todos os arquivos que estão disponíveis dentro do prefixo, conforme mostrado no código a seguir.

```
input_loc = "bucket-name/prefix/"
output_loc = "bucket-name/prefix/"

inputDyf = glueContext.create_dynamic_frame_from_options(
                    connection_type = "s3", 
                    connection_options = {"paths": [input_loc], 
                                            "compressionType":"gzip","recurse" :"True",
                                            },
                    format = "csv",
                    format_options={"withHeader": True,"separator": ","}
                    )
```

Para um grande número de arquivos pequenos compactados (por exemplo, 1.000 arquivos cada um com cerca de 133 KB), use o parâmetro `groupFiles` junto com os parâmetros `compressionType` e os parâmetros `recurse`. O parâmetro `groupFiles` agrupa arquivos pequenos em vários arquivos grandes e o parâmetro `groupSize` controla o agrupamento no tamanho especificado em bytes (por exemplo, 1 MB). O trecho de código a seguir fornece um exemplo do uso desses parâmetros no código.

```
input_loc = "bucket-name/prefix/"
output_loc = "bucket-name/prefix/"

inputDyf = glueContext.create_dynamic_frame_from_options(
                    connection_type = "s3", 
                    connection_options = {"paths": [input_loc], 
                                            "compressionType":"gzip","recurse" :"True",
                                             "groupFiles" :"inPartition",  "groupSize" :"1048576",
                                            },
                    format = "csv",
                    format_options={"withHeader": True,"separator": ","}
                    )
```

Sem nenhuma alteração nos nós de processamento, essas configurações permitem que o trabalho do AWS Glue leia vários arquivos (grandes ou pequenos, com ou sem compactação) e os grave no destino no formato Parquet.

**Trabalho do AWS Glue Spark com Scala**

Para usar um tipo de trabalho do AWS Glue Spark com Scala, escolha **Spark** como tipo de trabalho e **Linguagem** como **Scala**. Escolha o **Spark 3.1, Scala 2 com melhor tempo de startup do trabalho (Glue versão 3.0)** como a versão do AWS Glue. Para economizar espaço de armazenamento, o seguinte exemplo do AWS Glue com Scala também usa o atributo `applyMapping` para converter tipos de dados.

*Parâmetros do AWS Glue Scala*

```
import com.amazonaws.services.glue.util.GlueArgParser val args = GlueArgParser.getResolvedOptions(sysArgs, Seq("JOB_NAME", "inputLoc", "outputLoc").toArray)
```

*Trabalho do AWS Glue Spark com código Scala*

```
import com.amazonaws.services.glue.GlueContext
import com.amazonaws.services.glue.MappingSpec
import com.amazonaws.services.glue.DynamicFrame
import com.amazonaws.services.glue.errors.CallSite
import com.amazonaws.services.glue.util.GlueArgParser
import com.amazonaws.services.glue.util.Job
import com.amazonaws.services.glue.util.JsonOptions
import org.apache.spark.SparkContext
import scala.collection.JavaConverters._


object GlueScalaApp {
  def main(sysArgs: Array[String]) {
    
    @transient val spark: SparkContext = SparkContext.getOrCreate()
    val glueContext: GlueContext = new GlueContext(spark)

    val inputLoc = "s3://bucket-name/prefix/sample_data.csv"
    val outputLoc = "s3://bucket-name/prefix/"

    val readCSV = glueContext.getSource("csv", JsonOptions(Map("paths" -> Set(inputLoc)))).getDynamicFrame()

    val applyMapping = readCSV.applyMapping(mappings = Seq(("_c0", "string", "date", "string"), ("_c1", "string", "sales", "long"),
    ("_c2", "string", "profit", "double")), caseSensitive = false)

    val formatPartition = applyMapping.toDF().coalesce(1)

    val dynamicFrame = DynamicFrame(formatPartition, glueContext)

    val dataSink = glueContext.getSinkWithFormat(
        connectionType = "s3", 
        options = JsonOptions(Map("path" -> outputLoc )),
        transformationContext = "dataSink", format = "parquet").writeDynamicFrame(dynamicFrame)
  }
}
```

## Anexos
<a name="attachments-8c926709-8fa4-417f-9aaf-bcc8113d018f"></a>

Para acessar o conteúdo adicional associado a este documento, descompacte o seguinte arquivo:[ attachment.zip](samples/p-attach/8c926709-8fa4-417f-9aaf-bcc8113d018f/attachments/attachment.zip)