antonio leandro

dados e armazenamento

The Snowflake Elastic Data Warehouse

paper · núcleo · Benoit Dageville, et al. · · ~50 min de leitura do original

a tese

separar storage de compute não é economia de infra: é o que deixa cache ficar frio de propósito, upgrade rodar lado a lado e o usuário desligar todo o cluster sem mover um byte de dado

o que fica

  1. O arquivo de tabela é imutável porque o S3 é imutável, e dessa restrição saem quase de graça o MVCC, o snapshot isolation, o time travel e o clone sem cópia física.
  2. O cache local usa consistent hashing preguiçoso: quando um nó cai ou o warehouse muda de tamanho, nada é reembaralhado na hora e o LRU corrige sozinho ao longo das próximas queries.
  3. Snowflake abandonou índices e ficou só com poda min-max por arquivo, o que encolhe o espaço de planos do otimizador e elimina o tuning físico do usuário.
  4. Colunas dentro de dados semiestruturados são inferidas por análise estatística arquivo a arquivo, e o custo disso no TPC-H ficou em torno de 10% contra o esquema relacional.
  5. Upgrade online sem downtime só é possível porque todo estado duro mora num key-value transacional: duas versões do serviço rodam lado a lado e compartilham nós e caches.
  6. Os autores dizem que desempenho bruto quase nunca foi o gargalo percebido pelos usuários, porque subir um warehouse maior resolvia mais rápido que otimizar o motor.

o problema

Data warehouse de alto desempenho era sinônimo de shared-nothing: cada nó com seus discos locais, tabela particionada horizontalmente, pouca banda gasta para juntar uma dimensão pequena com um fato grande. O desenho é elegante e roda em hardware comum, mas amarra compute e storage no mesmo nó, e isso cobra três pedágios. Carga em massa quer muito I/O e pouca CPU; query complexa quer o contrário — com hardware homogêneo, a configuração vira meio-termo de utilização média baixa. Qualquer mudança no conjunto de nós, por falha ou por resize, obriga a reembaralhar dados nas mesmas máquinas que estão processando queries. E upgrade sem downtime é possível na teoria, mas penoso quando tudo é acoplado e se espera igual.

No on-prem dá para conviver: o pool é pequeno e fixo, falha é rara, resize é raro. Na nuvem, não. Os tipos de instância são muitos, falha de nó é frequente e o desempenho varia até entre nós do mesmo tipo — mudança de membership é a norma. O dado mudou junto: log de aplicação, mobile, sensor, chegando em JSON e Avro sem esquema, contra pipelines de ETL que pressupõem dado interno, previsível e lento. A alternativa da época era Hadoop ou Spark, que os autores classificam como indispensáveis para processamento em escala de datacenter e fracos em eficiência, conjunto de features e esforço de adoção.

a ideia

Cortar a máquina ao meio. O storage vira S3 — um blob store lento, caro por requisição, sem append, onde arquivo só se reescreve inteiro — e o compute vira cluster efêmero de EC2 que o usuário liga, redimensiona e desliga sem afetar o estado do banco. Entre os dois, uma terceira camada multi-tenant guarda o que sobrou: metadado, otimizador, transações, controle de acesso, chaves.

O disco local não some, muda de papel: em vez de guardar réplica da base inteira, guarda só cache e dado temporário, que são quentes. Uma vez aquecido, o cluster se comporta como shared-nothing; frio, ele degrada em vez de quebrar. É a inversão que os autores chamam de multi-cluster, shared-data.

como funciona

Tabelas são partidas em arquivos grandes e imutáveis em formato híbrido colunar, com header trazendo o offset de cada coluna — como o S3 aceita GET por range, a query baixa só o header e as colunas que interessam. Temporários de join e resultados também vão para o S3, o que remove cursor no servidor e o erro de disco cheio.

Cada virtual warehouse é um cluster privado, exposto em tamanhos de camiseta. Um worker process vive só o tempo da sua query e nunca produz efeito externo, então falha de worker se resolve com retry. O otimizador distribui os arquivos de entrada por consistent hashing sobre o nome do arquivo, para que o mesmo arquivo caia sempre no mesmo nó; quando o conjunto de nós muda, nada é reembaralhado e o LRU se encarrega. Contra straggler, file stealing: o nó que termina pede arquivos aos vizinhos, e quem cede transfere a posse, mas o pedinte baixa direto do S3 — não do peer sobrecarregado.

O motor é colunar, vetorizado e push-based, sem buffer pool e sem gerência de transação no caminho de execução, já que os arquivos são imutáveis. No lugar de índice, poda min-max: cada arquivo carrega mínimos e máximos, o otimizador descarta arquivos contra o predicado, e em runtime o lado build de um hash join empurra a distribuição das chaves para o lado probe descartar mais arquivos.

Semiestruturado entra como VARIANT. O sistema analisa estatisticamente os documentos de cada arquivo, extrai os paths frequentes para colunas comprimidas de verdade e ainda guarda Bloom filter sobre os paths presentes, para poder podar arquivo sem metadado da coluna. Datas em string passam por conversão otimista: guarda-se o valor convertido e a string original, e a coluna não usada nunca é lida.

o que isso custou

Warehouse não atravessa availability zone, por causa da banda de rede: falha de AZ inteira derruba as queries daquele warehouse e o usuário precisa reprovisionar na mão. Os autores aceitam explicitamente essa janela de indisponibilidade parcial. Não há retry parcial, então query muito longa que perde um nó recomeça. Nós não são compartilhados entre warehouses: o isolamento é forte e a utilização, baixa — sharing fica como trabalho futuro. Processos efêmeros cobram start-up em query pequena. O otimizador adia decisões para o runtime e troca pico de desempenho por previsibilidade. E a recusa a manter redo-undo ou delta store, por complexidade, significa que toda escrita reescreve arquivo inteiro — o desenho é para leitura em massa, não para update pontual. No próprio benchmark, o schema-less custou cerca de 10% em quase tudo, menos Q9 e Q17 no SF1000, onde um bug de estimativa de distinct escolheu ordem de join ruim.

onde isso aparece hoje

O paper se posiciona contra dois vizinhos que estão neste acervo: o Redshift, shared-nothing, onde redimensionar exige redistribuir dado, e o Dremel via BigQuery, que inspirou o suporte a dado aninhado mas exigia esquema e tabelas append-only. A ideia de espalhar cache por consistent hashing vem direto do trabalho de Karger. A separação entre storage e compute deixou de ser contrarian: virou premissa do lakehouse e é o eixo pelo qual o Redshift reaparece reinventado anos depois.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·