Getting Started
Este tutorial leva você do zero ao primeiro arquivo .permafrost em 5 minutos.
1. Instalação
Extras opcionais (cloud storage):
pip install permafrost-framework[s3] # AWS S3
pip install permafrost-framework[gcs] # Google Cloud Storage
pip install permafrost-framework[azure] # Azure Blob Storage
pip install permafrost-framework[all-cloud] # todos
Verifique a instalação:
2. Primeiro freeze
import permafrost as pf
import pandas as pd
import numpy as np
# Criar um dataset de exemplo
np.random.seed(42)
N = 50_000
df = pd.DataFrame({
"id": np.arange(1, N+1, dtype="int32"),
"data": pd.date_range("2022-01-01", periods=N, freq="30min"),
"ano": pd.date_range("2022-01-01", periods=N, freq="30min").year,
"regiao": np.random.choice(["Norte","Sul","Leste","Oeste"], N),
"total": np.round(np.random.uniform(1, 50000, N), 2),
"status": np.random.choice(["Ativo","Cancelado","Pendente"], N),
})
# Ordenar pela coluna de partição (importante para o sparse index)
df = df.sort_values("ano").reset_index(drop=True)
# Comprimir
metrics = pf.freeze(
df,
"vendas.permafrost",
codec=pf.CODEC_LZMA2, # melhor ratio para cold data
quant=pf.QUANT_NONE, # lossless (sem perda)
partition_by="ano", # habilita thaw seletivo por ano
chunk_rows=10_000, # linhas por chunk
comment="Vendas 2022-2024" # metadado livre
)
print(f"Original: {metrics['original_mb']:.2f} MB")
print(f"Arquivo: {metrics['stored_mb']:.3f} MB")
print(f"Ratio: {metrics['ratio']:.2f}×")
print(f"Redução: {metrics['reduction_pct']:.1f}%")
print(f"Tempo: {metrics['freeze_s']:.2f}s")
3. Inspecionar sem descomprimir
info = pf.audit("vendas.permafrost")
print(f"Versão: {info['version']}")
print(f"Codec: {info['codec']}")
print(f"Linhas: {info['orig_rows']:,}")
print(f"Chunks: {info['n_chunks']}")
print(f"Partição: {info['partition_col']}")
print(f"Anos: {info['partition_keys']}")
print(f"Colunas: {info['columns']}")
print(f"Freeze em: {info['freeze_date']}")
print(f"Comentário: {info['comment']}")
Zero decompressão
audit() lê apenas o header e o sparse index — os últimos bytes do arquivo.
Um arquivo de 2 GB é auditado em < 1ms.
4. Descomprimir (thaw)
Thaw completo
df_back = pf.unfreeze("vendas.permafrost", verify=True)
print(f"{len(df_back):,} linhas recuperadas")
Thaw seletivo — ler só 1 ano
df_2023 = pf.unfreeze("vendas.permafrost", filter={"ano": 2023})
# Lê apenas 12–31% do arquivo — não descomprime os outros anos
Thaw por range de linhas
5. Verificar integridade
# verify=True (padrão) verifica SHA-256 de cada chunk antes de descomprimir
df = pf.unfreeze("vendas.permafrost", verify=True)
# Verificação standalone (sem descomprimir)
import hashlib, struct
with open("vendas.permafrost", "rb") as f:
raw = f.read()
assert raw[:4] == b"PRMS", "Magic inválido"
assert raw[-4:] == b"SMRP", "EOF corrompido"
print("✓ Arquivo íntegro")
6. Vault mode (semi-lossy, ratio maior)
Para dados que só precisam de precisão razoável (compliance de longo prazo):
metrics_vault = pf.freeze(
df,
"vendas_vault.permafrost",
quant=pf.QUANT_MEDIUM # floats arredondados para inteiro, timestamps para minuto
)
print(f"Vault ratio: {metrics_vault['ratio']:.2f}×") # ~10×+ vs ~8.5× lossless
| Quant | Floats | Timestamps | Uso |
|---|---|---|---|
QUANT_NONE |
exatos | exatos | backup, compliance que precisa de precisão |
QUANT_HIGH |
1 decimal | exatos | analytics histórico |
QUANT_MEDIUM |
inteiro | floor(minuto) | cold storage de longo prazo |
QUANT_LOW |
dezena | floor(hora) | arquivamento extremo |
7. Encryption at rest (AES-256-GCM)
key = b"my-secret-key-exactly-32-bytes!!"
# Freeze with encryption — same API, just add key=
pf.freeze(df, "sensitive.permafrost", key=key)
# Thaw — provide the same key
df_back = pf.unfreeze("sensitive.permafrost", key=key)
# Selective read works on encrypted files too
df_2023 = pf.unfreeze("sensitive.permafrost", filter={"ano": 2023}, key=key)
Encryption is per-chunk (AES-256-GCM with unique nonce per chunk), so sparse index reads remain possible even on encrypted files. For production, use a KMS provider instead of a raw key.
8. PermafrostContext — API unificada (v1.0)
Para workflows mais completos, use PermafrostContext em vez de chamar
freeze(), thaw(), audit() e PermafrostCatalog separadamente:
# Tudo em um objeto — catalog + storage + cluster
ctx = pf.PermafrostContext(
catalog="catalog.db",
storage="s3://meu-bucket/cold/", # opcional
)
# Freeze + upload + catalog register em uma linha
metrics = ctx.freeze(df, "vendas_2024", partition_by="ano")
# Thaw com filtro
df_2023 = ctx.unfreeze("vendas_2024", filter={"ano": 2023})
# Buscar no catalog
ctx.search(name="vendas", lossless_only=True)
# Custo estimado
ctx.cost_report("glacier_deep")
# Context manager fecha conexões automaticamente
with pf.PermafrostContext(catalog="catalog.db") as ctx:
ctx.freeze(df, "backup_2024")
Veja a referência completa do PermafrostContext.
9. Próximos passos
-
PermafrostContext — API unificada para catalog + storage + cluster
-
Dados SQL & NoSQL — CSV, JSONL, MongoDB, DynamoDB
-
Cloud Storage — S3, GCS, Azure, audit sem download
-
Streaming — Datasets maiores que a RAM
-
Cluster — Processamento distribuído
-
Encryption — AES-256-GCM per chunk, KMS providers
9. Append — escrita incremental
Adicione novos dados a um arquivo existente sem precisar re-comprimir tudo:
# Arquivo já existe com 50.000 linhas
result = pf.append("vendas.pf", df_novos_registros)
print(f"Total de linhas: {result['total_rows']:,}")
print(f"Novos chunks: {result['new_chunks']}")
O append() preserva todos os dados originais, verifica integridade (SHA-256) e atualiza o sparse index. O schema novo precisa ser compatível com o original.
Veja o Guia de Append e o exemplo completo.
10. Diff — comparar versões
Compare dois arquivos .permafrost e veja o que mudou:
resultado = pf.diff("vendas_jan.pf", "vendas_fev.pf", output="summary")
print(resultado)
# {'deleted': 42, 'inserted': 89, 'changed': 317, 'unchanged': 49552}
# Ou como DataFrame com coluna _diff
df = pf.diff("vendas_jan.pf", "vendas_fev.pf", output="dataframe")
print(df.groupby("_diff").size())
O diff usa a primary_key embutida no arquivo para fazer o join. Sem primary key, usa posição e emite um aviso. Veja Guia de Diff.
11. Query SQL
Execute SQL diretamente sobre arquivos .permafrost/.pf usando DuckDB:
df = pf.query("""
SELECT regiao,
COUNT(*) AS transacoes,
ROUND(SUM(total), 2) AS receita
FROM 'vendas.pf'
GROUP BY regiao
ORDER BY receita DESC
""")
# JOIN entre dois arquivos
df = pf.query("""
SELECT v.regiao, SUM(v.total) AS receita, m.meta
FROM 'vendas.pf' v
JOIN 'metas.pf' m ON v.regiao = m.regiao
GROUP BY v.regiao, m.meta
""")
Não é necessário chamar unfreeze() antes — o motor descomprime apenas os chunks que o predicado de filtro precisar. Veja Guia de Query.
12. Exportar para CSV ou XLSX
O unfreeze() aceita output_format para exportar diretamente sem passar por DataFrame:
# CSV com separador personalizado (padrão: ',')
csv_bytes = pf.unfreeze("vendas.pf", filter={"ano": 2024},
output_format="csv", sep=";")
with open("vendas_2024.csv", "wb") as f:
f.write(csv_bytes)
# Excel
xlsx_bytes = pf.unfreeze("vendas.pf", filter={"ano": 2024},
output_format="xlsx")
with open("vendas_2024.xlsx", "wb") as f:
f.write(xlsx_bytes)