Data Lake
Partições Hive, camadas bronze/prata/ouro e compactação — em disco, sem servidor.
adopt Arcane.Lago as L
lago := L.lago("dados/")
L.gravar(lago, "vendas", linhas, ["ano", "mes"])
L.ler(lago, "vendas", {"ano": 2026})O caminho carrega o filtro#
dados/vendas/ano=2026/mes=03/parte-20260910-084726-0000.parquetUma consulta por ano=2026 não abre um arquivo sequer de 2025 — ela nem os lista. Com dois anos de dados isso é conveniência; com dez, é a diferença entre segundos e minutos.
O campo de partição sai das linhas antes de gravar: ele já está no caminho, e guardá-lo duas vezes é desperdício. Na leitura ele volta, vindo da pasta.
Gravar sempre acrescenta#
Cada gravação cria um arquivo com instante e contador no nome. Sobrescrever exigiria saber que a gravação anterior terminou, e num lago ninguém garante isso — quem quer trocar um período remove a partição antes:
L.remover_particao(lago, "vendas", {"ano": 2026, "mes": 3})
L.gravar(lago, "vendas", linhas_de_marco, ["ano", "mes"])Compactar#
Um lago que recebe carga de hora em hora acumula 24 arquivos por dia por partição. Ler mil arquivos de 4 KB é muito mais lento que ler um de 4 MB — o custo está em abrir, não em ler.
L.compactar(lago, "vendas")
// {"particoes_compactadas": 12, "arquivos_removidos": 276}Ele grava o arquivo novo inteiro antes de apagar os antigos. Apagar primeiro e falhar no meio perderia os dados.
As três camadas#
| Camada | O que guarda |
|---|---|
| bronze | o dado como chegou, sem tocar |
| prata | limpo, tipado, sem duplicata |
| ouro | agregado, pronto para consumo |
action limpar(linhas):
yield Q.so_validas(Q.sem_duplicadas(linhas, ["id"]), REGRAS)
L.gravar(L.camada(lago, "bronze"), "vendas", bruto, ["ano"])
L.promover(lago, "vendas", "bronze", "prata", limpar, ["ano"])
L.promover(lago, "vendas", "prata", "ouro", agregar, ["ano"])Inspecionar#
L.tabelas(lago) // as tabelas que existem
L.particoes(lago, "vendas") // as partições de uma delas
L.arquivos(lago, "vendas", {"ano": 2026})
L.esquema(lago, "vendas") // colunas, tipos, e quais são de partição
L.tamanho(lago) // bytes e arquivos, legível
L.eventos(lago) // o que aconteceu com o lago
L.vacuo(lago) // tira pasta vazia e gravação interrompidaO que este módulo não é#
Não é Delta Lake nem Iceberg. Não há transação ACID entre escritores concorrentes, nem viagem no tempo por versão, nem evolução de esquema automática.
Dois processos gravando na mesma partição ao mesmo tempo é o caso que ele não protege. Cada gravação cria um arquivo com nome próprio, então eles não se sobrescrevem — mas nada garante que os dois apareçam juntos para quem lê no meio.