(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como ler e escrever Parquet no PySpark: passo a passo

João Barros 11 de July de 2026 4 min de leitura

Parquet é o formato de ficheiro mais usado em projetos de dados com Spark: guarda a informação por colunas, ocupa muito menos espaço do que um CSV e permite ler apenas as colunas de que precisas. Saber ler e escrever Parquet no PySpark é, por isso, um dos passos essenciais para construir pipelines rápidos e baratos num Lakehouse. Vamos fazê-lo com exemplos mínimos que podes copiar e correr já.

Pré-requisitos

  • Um ambiente com PySpark: Databricks, Microsoft Fabric, Azure Synapse ou pip install pyspark no teu computador.
  • Python 3.8 ou superior e Java 11 (só necessário se correres o Spark localmente).
  • Noções básicas de DataFrames: select, filter e show.
  • Uma pasta onde possas escrever ficheiros (disco local ou armazenamento cloud).

Passo 1: Criar a sessão Spark e um DataFrame de exemplo

Para escrever Parquet no PySpark precisas de uma SparkSession e de dados. Em Databricks, Fabric ou Synapse a variável spark já existe — nesse caso salta as duas primeiras linhas.

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("parquet-demo").getOrCreate()

dados = [
    ("Ana", "Lisboa", 2025, 1200.0),
    ("Bruno", "Porto", 2025, 890.5),
    ("Carla", "Lisboa", 2026, 1540.0),
    ("Diogo", "Faro", 2026, 730.25),
]
vendas = spark.createDataFrame(dados, ["vendedor", "cidade", "ano", "valor"])
vendas.show()

Passo 2: Escrever o DataFrame em Parquet

A escrita faz-se com write.parquet(). Há aqui um detalhe que confunde muita gente no início: o caminho que indicas não é um ficheiro, é uma pasta. O Spark cria lá dentro vários ficheiros .parquet, um por cada partição que tem em memória, mais alguns ficheiros de controlo.

vendas.write.mode("overwrite").parquet("/tmp/vendas_parquet")

O mode define o que acontece quando a pasta já existe:

  • overwrite: apaga o conteúdo anterior e volta a escrever.
  • append: acrescenta novos ficheiros aos que já lá estão.
  • error (predefinido): falha com o erro path already exists.
  • ignore: não escreve nada se a pasta já existir.

Passo 3: Particionar os dados com partitionBy

Se filtras quase sempre pela mesma coluna (ano, país, data), guarda os dados particionados. O Spark cria uma subpasta por valor e, na leitura, ignora as pastas que não interessam — chama-se a isto partition pruning e é o que faz as queries ficarem rápidas.

(vendas.write
    .mode("overwrite")
    .partitionBy("ano")
    .parquet("/tmp/vendas_por_ano"))

No disco fica assim:

/tmp/vendas_por_ano/ano=2025/part-00000-....snappy.parquet
/tmp/vendas_por_ano/ano=2026/part-00000-....snappy.parquet
Dica: particiona por colunas com poucos valores distintos (dezenas ou centenas). Particionar por uma coluna com milhares de valores cria milhares de ficheiros minúsculos e torna tudo mais lento, não mais rápido.

Passo 4: Ler ficheiros Parquet

Para ler, basta apontar para a pasta. Ao contrário do CSV, não precisas de declarar o schema nem de usar inferSchema: os nomes e os tipos das colunas estão guardados dentro do próprio ficheiro Parquet.

df = spark.read.parquet("/tmp/vendas_por_ano")
df.printSchema()

# apenas as linhas de 2026: o Spark lê só a subpasta ano=2026
df_2026 = df.filter(df.ano == 2026)
df_2026.show()

Como o Parquet é colunar, também podes pedir apenas as colunas de que precisas — o Spark nem chega a ler as restantes do disco:

df.select("vendedor", "valor").show()

Passo 5: Compressão e número de ficheiros

Por omissão o Spark comprime com snappy, que é o melhor equilíbrio entre tamanho e velocidade. Se precisares de ficheiros ainda mais pequenos, usa gzip. E quando o resultado é pequeno, junta tudo num único ficheiro com coalesce(1) para evitar o problema dos small files.

(vendas
    .coalesce(1)
    .write
    .mode("overwrite")
    .option("compression", "gzip")
    .parquet("/tmp/vendas_pequeno"))

Verificar o resultado

Volta a ler o que escreveste e confirma três coisas: o número de linhas, os tipos das colunas e as partições criadas.

lido = spark.read.parquet("/tmp/vendas_por_ano")

print(lido.count())               # deve devolver 4
lido.printSchema()                # valor: double, ano: integer
lido.groupBy("ano").count().show()  # 2 linhas por ano

Se o count() devolver 4 e o schema mostrar valor como double, está tudo bem — os tipos sobreviveram à ida ao disco, coisa que não acontece com CSV. O erro mais comum nesta fase é Unable to infer schema for Parquet: quase sempre significa que o caminho está errado ou que a pasta está vazia.

Conclusão

Com write.parquet(), partitionBy() e read.parquet() já tens o essencial para trocar os teus CSV por um formato que poupa espaço e tempo de leitura. O passo seguinte natural é evoluir para tabelas Delta Lake, que acrescentam transações ACID, histórico de versões e MERGE por cima destes mesmos ficheiros Parquet. Antes disso, faz uma experiência: escreve o mesmo DataFrame em CSV e em Parquet e compara o tamanho das pastas — qual foi a diferença no teu caso?