Pular para o conteúdo
Lucas Lessa

Trilha de certificações

Associate

Databricks Certified Associate Developer for Apache Spark

Avalia a arquitetura do Apache Spark e o uso da DataFrame API em Python: manipular colunas e linhas, agregações, joins, leitura e escrita com schema, UDFs, Spark SQL, Structured Streaming, Spark Connect, Pandas API on Spark e tuning básico.

Formato da prova

Questões
45 questões
Duração
90 min
Taxa
US$ 200
Idiomas
Inglês
Validade
2 anos
Versão do guia oficial
08 de out. de 2026

Nenhum obrigatório. Recomenda-se seis meses de prática com Apache Spark.

O que cai e quanto pesa

Número aproximado de questões por seção, considerando as 45 questões pontuadas.

Seção 1 · 20% · ≈ 9 questões

Arquitetura e componentes do Spark

Objetivos oficiais

  • Identificar vantagens e desafios de usar Spark.
  • Identificar o papel dos componentes: cluster, driver, workers/executores, núcleos de CPU e memória.
  • Descrever a arquitetura: DataFrame e Dataset, ciclo de vida da SparkSession, cache, storage levels e garbage collection.
  • Explicar a hierarquia de execução.
  • Configurar o particionamento: shuffles e partições.
  • Descrever os padrões de execução: actions, transformations e lazy evaluation.
  • Identificar os módulos: Core, Spark SQL, DataFrames, Pandas API on Spark, Structured Streaming e MLlib.

Quem faz o quê

  • Driver: roda seu programa, cria o plano, divide em jobs/stages/tasks e agenda.
  • Executores (nos workers): executam tasks e guardam dados em cache. Cada core executa uma task por vez.
  • Cluster manager: entrega recursos (standalone, YARN, Kubernetes; na Databricks, gerenciado).

Hierarquia de execução

Application → Job (uma por action) → Stage (fronteira = shuffle) → Task (uma por partição).

Lazy evaluation

Transformations (select, filter, withColumn, join, groupBy) só constroem o plano. Actions (count, collect, show, take, write) disparam a execução. Isso deixa o Catalyst otimizar o plano inteiro (ex.: empurrar filtros para a leitura).

  • Narrow (sem shuffle): filter, select, map.
  • Wide (com shuffle): groupBy, join, distinct, orderBy, repartition.

Partições

spark.sql.shuffle.partitions (padrão 200) define quantas partições saem de um shuffle. repartition(n) faz shuffle e pode aumentar/diminuir; coalesce(n) só diminui, sem shuffle completo.

Cache e storage levels

df.cache() = persist(StorageLevel.MEMORY_AND_DISK) para DataFrames (no PySpark recente aparece como MEMORY_AND_DISK_DESER, a variante desserializada). Outras: MEMORY_ONLY, DISK_ONLY, _SER, _2 (replicado). O cache também é lazy: só materializa na próxima action. unpersist() libera.

GC

Muito objeto na JVM → pausas de garbage collection (veja "GC time" na Spark UI). Ajuda: menos dados em cache, formatos serializados, partições menores, evitar UDFs Python que criam muitos objetos.

Vantagens e desafios

Processamento distribuído em memória, APIs unificadas (SQL, Python, streaming, ML), tolerância a falhas por linhagem. Desafios: tuning (memória, partições, skew), custo de shuffle, curva de aprendizado.

Pegadinhas comuns

  • coalesce não aumenta o número de partições.
  • cache() não executa nada sozinho.

Documentação:Visão geral do clusterRDD persistence / storage levels

Seção 2 · 20% · ≈ 9 questões

Spark SQL

Objetivos oficiais

  • Usar fontes comuns (JDBC, arquivos) para ler e escrever DataFrames, incluindo sobrescrita e particionamento por coluna.
  • Executar SQL direto sobre arquivos (ORC, JSON, CSV, texto, Delta) e entender os save modes.
  • Salvar dados em tabelas persistentes aplicando ordenação e particionamento para otimizar a leitura.
  • Registrar DataFrames como views temporárias e consultá-los com SQL.

Ler e escrever

df = (spark.read.format("csv").option("header", True).schema("id INT, pais STRING, valor DOUBLE")
        .load("/data/vendas.csv"))
df.write.mode("overwrite").partitionBy("pais").parquet("/data/out")

jdbc = (spark.read.format("jdbc")
          .option("url", "jdbc:postgresql://db:5432/erp").option("dbtable", "public.clientes")
          .option("user", u).option("password", p).load())

Save modes

ModoSe o destino existe
error / errorifexists (padrão)Falha
appendAcrescenta
overwriteSubstitui
ignoreNão faz nada

SQL direto em arquivos

SELECT * FROM parquet.`/data/out`;
SELECT * FROM json.`/data/eventos/*.json`;
SELECT * FROM delta.`/data/tabela_delta`;

Tabelas persistentes

df.write.partitionBy("ano").sortBy("id").bucketBy(8, "id").saveAsTable("vendas")   # sortBy exige bucketBy

saveAsTable registra no metastore/catálogo; continua existindo depois da sessão.

Views temporárias

df.createOrReplaceTempView("vendas_v")          # só nesta SparkSession
df.createOrReplaceGlobalTempView("vendas_g")    # global_temp.vendas_g, todas as sessões da aplicação
spark.sql("SELECT pais, SUM(valor) FROM vendas_v GROUP BY pais").show()

Pegadinhas comuns

  • O save mode padrão é errorifexists, não overwrite.
  • Global temp view fica no schema global_temp.

Documentação:Data sourcesSave modes

Seção 3 · 30% · ≈ 14 questões

Aplicações com a DataFrame/Dataset API

Objetivos oficiais

  • Manipular colunas, linhas e estrutura: adicionar, remover, dividir e renomear colunas, filtrar e explodir arrays.
  • Deduplicar e validar DataFrames.
  • Agregar: count, contagem distinta aproximada, média e summary.
  • Manipular datas: epoch Unix para string de data e extrair componentes.
  • Combinar DataFrames com inner, left, broadcast, múltiplas chaves, cross join, union e union all.
  • Ler, escrever e sobrescrever DataFrames com schema.
  • Ordenar, iterar, imprimir o schema e converter DataFrame em lista.
  • Criar e invocar UDFs com ou sem operadores com estado (StateStore).
  • Descrever variáveis broadcast e acumuladores.
  • Descrever o propósito e a implementação de broadcast joins.

Colunas

from pyspark.sql import functions as F

df = (df.withColumn("state", F.col("division")).drop("division")
        .withColumnRenamed("mName", "managerName")
        .withColumn("partes", F.split("endereco", ","))
        .withColumn("tag", F.explode("tags"))
        .filter((F.col("valor") > 0) & F.col("pais").isin("BR", "PT")))

Nulos e duplicatas

df.na.drop() (= how="any": remove linha com qualquer nulo); na.drop("all") só se todas forem nulas; subset=[...]; na.fill({"col": 0}); dropDuplicates(["id"]); distinct().

Agregações

df.groupBy("pais").agg(F.count("*").alias("n"), F.avg("valor"), F.approx_count_distinct("usuario"))
df.summary().show()   # count, mean, stddev, min, 25%, 50%, 75%, max

approx_count_distinct usa HyperLogLog: muito mais barato que countDistinct, com erro pequeno configurável.

Datas

df.withColumn("data", F.from_unixtime("epoch", "yyyy-MM-dd")) \
  .withColumn("ts", F.to_timestamp(F.from_unixtime("epoch"))) \
  .withColumn("ano", F.year("ts")).withColumn("mes", F.month("ts")).withColumn("dia_semana", F.dayofweek("ts"))

Joins e unions

a.join(b, ["id", "data"], "left"), a.crossJoin(b), a.join(F.broadcast(b), "id"). union (= UNION ALL, por posição), unionByName (por nome; allowMissingColumns=True).

Ordenar, schema, listas

linhas = df.orderBy(F.col("salary").desc(), F.col("age").desc()).collect()   # lista de Row
df.printSchema()
lista = [r.asDict() for r in linhas]
for r in df.toLocalIterator(): ...      # itera sem trazer tudo de uma vez

UDFs

@F.udf("string")
def normaliza(s): return s.strip().lower() if s else None
df.withColumn("nome_n", normaliza("nome"))
spark.udf.register("normaliza", normaliza)   # usar em SQL

Prefira funções nativas (mais rápidas). UDF sem estado aplica lógica por linha; lógica com estado entre eventos (sessões, totais acumulados) usa operadores com estado de streaming (applyInPandasWithState, transformWithState) que guardam dados no StateStore.

Broadcast e acumuladores

  • Broadcast variable: valor somente leitura enviado uma vez por executor (ex.: dicionário de lookup).
  • Accumulator: contador que os executores só somam e o driver lê (ex.: contar registros inválidos).
  • Broadcast join: a tabela pequena vai inteira para cada executor → a grande não precisa de shuffle. Automático abaixo de spark.sql.autoBroadcastJoinThreshold (10 MB) ou com F.broadcast().

Pegadinhas comuns

  • df.na.drop() sem argumentos já é how='any'.
  • union junta por posição; colunas em ordem diferente geram dados trocados sem erro.
  • collect() traz tudo para o driver — cuidado com OOM.

Documentação:PySpark APIFunções SQL

Seção 4 · 10% · ≈ 5 questões

Troubleshooting e tuning

Objetivos oficiais

  • Aplicar estratégias de desempenho e uso do cluster: particionar, reparticionar, coalescer, identificar skew e reduzir shuffle.
  • Descrever o Adaptive Query Execution (AQE) e seus benefícios.
  • Fazer logging e monitoramento: publicar, customizar e analisar logs de driver e executores para diagnosticar OOM, subutilização etc.

Estratégias

  • Poucas partições → cores ociosos; muitas → overhead. Regra prática: partições de ~100–200 MB, pelo menos 2–3× o número de cores.
  • Skew: uma chave com muito mais dados → uma task lenta. Veja Max ≫ Median na Spark UI. Soluções: AQE skew join, salting, broadcast.
  • Menos shuffle: filtre e selecione cedo, broadcast de tabelas pequenas, evite distinct/orderBy desnecessários.

AQE (ligado por padrão desde o Spark 3.2)

Reotimiza o plano em tempo de execução com estatísticas reais:

  1. Coalesce de partições pós-shuffle (junta partições pequenas);
  2. Troca de estratégia de join (sort-merge → broadcast quando um lado ficou pequeno);
  3. Skew join (divide partições gigantes).

Logs

Logs de executor e driver pela Spark UI (aba Executors → stdout/stderr) ou pelos logs do cluster. spark.sparkContext.setLogLevel("WARN") ajusta o nível; use log4j2 para customizar. Sinais: OutOfMemoryError no driver (collect grande), executor lost/OOM (partições grandes, skew), CPU ociosa (poucas partições).

Documentação:AQEMonitoramento

Seção 5 · 10% · ≈ 5 questões

Structured Streaming

Objetivos oficiais

  • Explicar o engine: modelo de programação, micro-batches, semântica exactly-once e tolerância a falhas.
  • Criar e gravar Streaming DataFrames/Datasets com os output modes e sinks básicos.
  • Fazer operações básicas: seleção, projeção, janela e agregação.
  • Fazer deduplicação em streaming com e sem watermark.

Modelo

O stream é uma tabela sem fim; sua query roda incrementalmente em micro-batches. Checkpoint (offsets + estado) + fonte reprocessável + sink idempotente = exactly-once.

eventos = (spark.readStream.format("json").schema(schema).load("/data/in"))

contagem = (eventos.withWatermark("ts", "10 minutes")
              .groupBy(F.window("ts", "15 minutes", "5 minutes"), "produto").count())

(contagem.writeStream.outputMode("update").format("console")
   .option("checkpointLocation", "/chk/contagem").trigger(processingTime="2 minutes").start())

Output modes

append (só linhas novas/finais), update (linhas que mudaram), complete (resultado inteiro — só com agregação).

Sinks

File (parquet, json…), Kafka, foreach / foreachBatch, console e memory (debug), tabelas (toTable).

Deduplicação

eventos.dropDuplicates(["evento_id"])                                   # estado cresce para sempre
eventos.withWatermark("ts", "1 hour").dropDuplicates(["evento_id", "ts"])  # estado limitado pela watermark
eventos.withWatermark("ts", "1 hour").dropDuplicatesWithinWatermark(["evento_id"])

Documentação:Structured Streaming

Seção 6 · 5% · ≈ 2 questões

Spark Connect e modos de deploy

Objetivos oficiais

  • Descrever os recursos do Spark Connect.
  • Descrever os modos de deploy (client, cluster e local).

Spark Connect

Arquitetura cliente-servidor: o cliente leve (Python, Scala, Go…) envia planos lógicos via gRPC para o servidor Spark remoto. Vantagens: rodar Spark a partir de IDEs, notebooks e apps sem JVM local; isolamento (um cliente que trava não derruba o driver); upgrades independentes. SparkSession.builder.remote("sc://host:15002").getOrCreate(). Na Databricks, é a base do Databricks Connect e do serverless.

Modos de deploy

ModoOnde fica o driver
ClientNa máquina que submeteu (bom para interativo)
ClusterDentro do cluster (bom para produção; independe da máquina do usuário)
LocalTudo em uma JVM numa máquina; executores são threads (local[*]) — testes e desenvolvimento

Documentação:Spark Connect

Seção 7 · 5% · ≈ 2 questões

Pandas API on Spark

Objetivos oficiais

  • Explicar as vantagens da Pandas API on Spark.
  • Criar e invocar Pandas UDFs.

Pandas API on Spark

import pyspark.pandas as ps
psdf = ps.read_csv("/data/vendas.csv")
psdf.groupby("pais")["valor"].mean().sort_values()
psdf.to_spark()     # volta a ser DataFrame do Spark; df.pandas_api() faz o caminho inverso

Sintaxe do pandas com execução distribuída — migração de código pandas para dados que não cabem numa máquina.

Pandas UDF

import pandas as pd
from pyspark.sql.functions import pandas_udf

@pandas_udf("double")
def com_imposto(valor: pd.Series) -> pd.Series:
    return valor * 1.1

df.withColumn("valor_final", com_imposto("valor"))

Vetorizada com Apache Arrow: processa lotes inteiros, muito mais rápida que UDF Python linha a linha.

Documentação:Pandas API on Spark

Treinamentos recomendados pela Databricks

  • Instrutor: Apache Spark Programming with Databricks
  • Academy: Introduction to Apache Spark
  • Academy: Developing Applications with Apache Spark
  • Academy: Stream Processing and Analysis with Apache Spark
  • Academy: Monitoring and Optimizing Apache Spark Workloads on Databricks
Guia do exame Apache Spark Developer Associate · Lucas Lessa