SELECT

SELECT

Reduza os custos do Databricks depois que os ganhos fáceis acabarem

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

By SELECTNov 12, 2022 min read

TL;DR

Os ganhos rápidos na otimização de custos do Databricks (auto-termination, timeouts, autoscaling, compute dimensionado corretamente) são o melhor retorno que você vai conseguir: costumam cortar de 20 a 40% da fatura e levam minutos para aplicar. Além deles, outros 20 a 40% geralmente estão disponíveis, mas custam dias ou semanas de esforço e só compensam nos workloads em que a conta fecha. Este guia é sobre esse segundo nível: como encontrar os jobs que valem o esforço e como fazê-los trabalhar menos antes de decidir em que compute executá-los.

Introdução

A maior parte dos conselhos sobre custos do Databricks para na configuração. Configure auto-termination, adicione timeouts, ative o autoscaling, pare de superdimensionar seus clusters. Esse conselho está correto, e você deveria fazer tudo isso primeiro, porque é de fato o trabalho de maior retorno disponível. Dependendo do seu ponto de partida, esses ganhos rápidos costumam recuperar de 20 a 40% da fatura, e a maioria leva minutos. Ninguém deveria pular essa etapa, e este post não está dizendo que ela é pequena.

A questão é que ela tem um teto. Quando os clusters ociosos somem, os timeouts estão configurados e o compute está dimensionado corretamente, você capturou uma grande economia pontual e a curva se achata. Os workloads em si continuam fazendo exatamente a mesma quantidade de trabalho de antes. Conseguir os próximos 20 a 40% significa mudar o que os jobs realmente fazem: um pipeline que reprocessa todo o histórico toda noite, uma query que escaneia cem vezes mais dados do que retorna, um dashboard "em tempo real" que ninguém abre mais de uma vez por dia. Nada disso fica mais barato quando você redimensiona o cluster. Fica mais barato quando você redesenha o trabalho, e isso custa dias ou semanas em vez de minutos. Também só compensa em alguns workloads, e é por isso que o primeiro passo de verdade é descobrir quais. Este guia é sobre esse segundo nível.

Por que a maioria dos esforços de redução de custos do Databricks empaca depois dos ganhos fáceis?

A primeira investida nos custos do Databricks quase sempre mira o mesmo punhado de controles, e por um bom motivo. São as correções de maior retorno e menor esforço disponíveis, e pulá-las é o caminho para a fatura sair do controle. Se você ainda não as fez, comece por aí: nosso guia Databricks Pricing Explained detalha auto-termination, timeouts e Job Compute versus all-purpose. Trate aquele post como pré-requisito e este como o próximo passo.

Eis o problema de parar por aí. Cada um desses controles é uma correção pontual. O auto-termination impede que você pague por clusters ociosos, mas quando o tempo ocioso chega a zero, não há mais nada a recuperar. Mover um pipeline de um cluster all-purpose a $0,55 por DBU para o Jobs Classic a $0,30 por DBU corta a taxa daquele job em cerca de 45%, mas essa troca só pode ser feita uma vez. São ganhos grandes e rápidos, frequentemente de um quinto a dois quintos da fatura, e depois acabam. A curva se achata e a fatura se acomoda em uma nova base, mais baixa, que fica estacionada ali.

Essa base é definida por quanto trabalho seus jobs fazem, e essa é a variável que os ganhos rápidos nunca tocam. Um pipeline diário que reescreve por completo uma tabela de um bilhão de linhas é caro mesmo no cluster de Jobs mais barato e corretamente dimensionado que você conseguir provisionar. O próximo nível de economia mora no próprio workload: processar menos dados, rodar com menos frequência, calcular resultados uma vez em vez de repetidamente. Isso é mais difícil do que alternar uma opção de configuração, leva dias ou semanas em vez de minutos e não compensa em todo lugar. Em um pipeline barato ou pouco frequente, o tempo de engenharia vai custar mais do que a economia. É exatamente por isso que o próximo passo não é começar a otimizar, é descobrir quais workloads valem a otimização.

Como encontrar os workloads que valem a otimização?

Antes de otimizar qualquer coisa, descubra o que é realmente caro. Isso importa mais do que parece, porque a intuição da engenharia e a fatura raramente apontam para a mesma coisa. O pipeline que você acha irritante costuma ser barato. Aquele em que ninguém pensa roda em um cluster grande três vezes por dia e domina a fatura em silêncio.

A forma mais rápida de ranquear seus gastos são as system tables de billing. Faça o join de system.billing.usage (cada DBU consumido) com system.billing.list_prices (o preço efetivo por SKU) para transformar quantidades em dólares, e depois o join com system.lakeflow.jobs para anexar um nome de job legível, de modo que o ranking seja de fato acionável:

WITH price AS (
SELECT
sku_name,
pricing.effective_list.default AS price_effective
FROM system.billing.list_prices
WHERE
price_end_time IS NULL
),
usage AS (
SELECT
*
FROM
system.billing.usage
WHERE
usage.billing_origin_product = 'JOBS'

Expandir código

Isso ranqueia seus jobs por custo diário com os nomes anexados, o que responde à única pergunta que importa nesta etapa: quais jobs nomeados estão pesando na fatura? Aliás, o join com system.lakeflow.jobs é o que faz o tagueamento valer a pena. Tags nunca reduzem a fatura por si só, mas são elas que permitem agrupar essa saída por time, ambiente ou projeto em vez de se afogar em IDs e nomes de jobs que mudam com o tempo.

A razão para ranquear antes de agir é que a otimização tem um custo próprio, e é fácil gastar mais tempo de engenharia do que se economiza. Reescrever um pipeline que representa 1% da fatura é um exercício satisfatório que nunca vai aparecer na fatura, e as horas gastas nele geralmente vão superar em muito a economia por anos. Ordene por custo, olhe o punhado de workloads no topo e ignore a cauda longa até que os caros estejam resolvidos. Otimize os outliers, não tudo.

Ranquear seus próprios gastos por workload significa escrever e manter essas queries, e depois manter os dashboards atualizados conforme jobs são renomeados e pipelines evoluem. O SELECT faz essa atribuição automaticamente, revelando seus workloads mais caros, compute ocioso e incompatibilidades de tipo de compute sem a construção manual de queries. Veja o que ele encontra no seu ambiente.

Por que otimizar o job supera redimensionar o cluster?

Esta é a seção que compensa todo o resto. Quando um job está lento ou caro, a correção instintiva é um cluster maior, porque é uma única configuração e geralmente funciona. É também a correção mais cara disponível, e deixa o desperdício subjacente intacto. Um job que escaneia mais dados do que precisa, faz shuffles desnecessários ou reprocessa um histórico que já processou vai queimar compute em excesso em qualquer tamanho de cluster. Escalar só paga esse imposto mais rápido.

Para tornar isso concreto: um cliente meu rodava um pipeline de dados de IoT que reduzimos em cerca de 85% no tempo de execução e 75% no custo, aproximadamente $10.000 por ano, no mesmo ambiente. O compute não estava mal dimensionado de início; não era ideal, mas tampouco absurdo. Redimensioná-lo mudaria a fatura em percentuais de um dígito. A economia veio inteiramente de mudar o que o pipeline fazia: carga incremental das camadas bronze e silver em vez de reprocessamento completo, adiamento de um join caro com uma tabela fato para depois que a agregação diária tivesse encolhido os dados, reescrita da transformação mais pesada e consumo servido por views em vez de duplicar dados em novas tabelas. Cada um desses itens corresponde a uma das alavancas abaixo. Nenhum deles sozinho foi a história toda, e o dimensionamento de compute não estava na lista.

Leia o query profile e depois redesenhe a parte cara

O Databricks expõe um query profile detalhado para cada execução, mostrando onde o tempo foi gasto em cada estágio do plano. A partir do histórico de queries, ou diretamente de um job ou query SQL, você pode abrir o profile e baixar o plano de execução completo em JSON. Esse JSON é o insumo para o truque de maior alavancagem e menos conhecido do workflow moderno de engenharia de dados: entregá-lo a um LLM.

Um LLM é muito bom em ler um query profile e dizer onde está o custo: qual estágio teve spill, qual join explodiu, onde um shuffle rodou em muito mais partições do que os dados justificavam. Em um job real, um deles apontou que o gargalo era uma transformação SQL que construía um calendário de datas completo (uma linha por entidade por dia, ao longo de cerca de catorze anos de histórico) e depois o colapsava de volta, produzindo dezenas de milhões de linhas intermediárias para calcular um resultado que precisava de uma fração minúscula disso. E ele não parou no diagnóstico. Propôs uma primeira reescrita em PySpark usando uma abordagem baseada em eventos, de varredura de intervalos, que nunca materializa o calendário, e dali em diante virou um colaborador de verdade na solução. Eu apontava um caso extremo que a primeira versão não tratava, ele incorporava a correção, capturávamos esse caso como teste unitário, e iteramos esse ciclo por dois ou três dias até os resultados estarem corretos em todos os cenários. O job diário caiu de cerca de duas horas para dez minutos, uma redução de aproximadamente 15x tanto no tempo de execução quanto no custo em DBUs.

A questão é a divisão de trabalho, e não é "a IA aponta problemas, o humano faz o trabalho de verdade". O modelo encontrou o gargalo, propôs o algoritmo e escreveu a maior parte do código. Meu papel era conduzir: pegar os casos que ele deixava passar, decidir quando a solução estava de fato correta e manter a iteração honesta com testes. Esse é um uso bem diferente e muito mais poderoso do que colar uma mensagem de erro. Se você edita no workspace do Databricks, o Genie dá conta do recado; se está na sua IDE, qualquer assistente já integrado funciona igualmente bem. A ferramenta importa menos do que o hábito de ler o profile e reconstruir a parte cara em vez de recorrer a um cluster maior.

Adote o incremental em vez de sobrescrever a tabela inteira

O overwrite completo é o padrão de pipeline mais simples, e para tabelas pequenas ou de tamanho moderado costuma ser a escolha certa. A complexidade do processamento incremental nem sempre vale a pena. Mas quando os volumes de dados são altos, especialmente para dados transacionais, telemetria ou séries temporais, reprocessar a tabela inteira a cada execução fica mais caro e mais difícil de justificar a cada vez que a tabela cresce.

A alternativa incremental é fazer append de novos registros para dados imutáveis, ou merge de registros alterados para dados que são atualizados, e levar esse padrão pelo maior número possível de camadas da sua arquitetura medallion. Só quando os dados são agregados até algo pequeno é que um overwrite completo volta a ser razoável. O Spark Structured Streaming é a ferramenta prática aqui: combinado com o Auto Loader para ingestão de arquivos ou lendo nativamente de uma tabela Delta, ele gerencia checkpoints automaticamente, de modo que cada execução processa apenas o que chegou desde a última. O maior ganho para a maioria dos times não é o processamento contínuo em tempo real, é o padrão confiável de batch incremental que o streaming facilita, processando dados novos sem reescanear o que já existe.

Questione o requisito de "tempo real" antes de aceitá-lo

"Precisamos de dados quase em tempo real" é um dos requisitos mais caros que um time de dados pode aceitar sem questionar, e muito raramente é verdade. Stakeholders quase nunca precisam de um fluxo contínuo de dados frescos. Eles precisam de uma visão recente o suficiente quando de fato olham, o que é algo completamente diferente e muito mais barato. Antes de construir para tempo real, descubra com que frequência o dashboard é realmente aberto e com que frequência o relatório é realmente lido. Atualizações de hora em hora, diárias ou até semanais são suficientes com muito mais frequência do que o pedido original sugere.

A diferença de custo não é marginal. Pegue um pipeline ilustrativo e mantenha o trabalho constante mudando apenas a cadência: rodando continuamente, ele pode custar 58 unidades; de hora em hora, o mesmo trabalho cai para cerca de 5 unidades; três vezes por dia, você chega perto de 1 unidade. Isso não é diferença de arredondamento: é cerca de 12x do contínuo para o horário, e mais um grande degrau para baixo a partir daí.

Na prática, o caminho é construir todo pipeline com Structured Streaming independentemente da frequência pedida no início, porque o streaming torna trivial alternar entre batch agendado e operação contínua. Depois, comece na menor frequência que atenda à necessidade real do negócio e aumente apenas quando houver evidência concreta de que é preciso mais atualidade nos dados. A capacidade de escalar está lá quando você precisar; a economia de não escalar prematuramente chega imediatamente.

Crie views em vez de tabelas

Nem toda tabela precisa guardar dados fisicamente. Boa parte das tabelas em um ambiente típico de Databricks existe não por causa de transformações complexas, mas para expor dados em outro formato: outro schema, um filtro, um subconjunto de colunas, outro conjunto de permissões de acesso. Nesses casos, copiar os dados fisicamente adiciona custo de armazenamento, custo de compute e complexidade de pipeline sem benefício real.

Uma view é a ferramenta certa para isso. É uma camada virtual definida por uma query, sem nada copiado ou armazenado, e para uma seleção simples de colunas ou um filtro, a experiência de leitura é indistinguível da de uma tabela. Reserve tabelas físicas para as saídas de transformações realmente caras, em que materializar o resultado economiza recomputação significativa. Para todo o resto, uma view mantém o armazenamento enxuto e os pipelines mais simples. Para um tratamento mais profundo desses padrões de workflow, nosso ebook gratuito de otimização de custos os percorre com o fluxograma de diagnóstico que usamos para decidir qual alavanca se aplica a cada workload.

Como escolher o compute certo depois que o job está eficiente?

Repare na ordem. A seleção de compute vem depois da otimização do workload, não antes, e essa sequência é o argumento central deste post. Dimensionar compute para um job ineficiente só cristaliza o desperdício na escala que você escolheu. Quando o job faz a quantidade certa de trabalho, a decisão de compute fica mais simples e o que está em jogo diminui.

O padrão deve ser serverless, em tudo: jobs, notebooks e SQL. Isso pode parecer errado, porque o serverless tem uma taxa por DBU mais alta: no Azure Premium, o Jobs Serverless sai a $0,45 por DBU contra $0,30 do Jobs Classic, e o Serverless interativo custa $0,95 contra $0,55 do all-purpose clássico. Mas a taxa por DBU é só metade da história, e esta é a parte que os times mais deixam passar quando fazem a comparação. No compute clássico, a cobrança de DBU não é a fatura inteira. Você também paga separadamente ao seu provedor de nuvem pelas VMs subjacentes, e esse número é realmente difícil de estimar com antecedência. O serverless embute a infraestrutura na taxa de DBU, então o preço que você vê é o preço que você paga.

Esse pacote inverte a comparação simplista com mais frequência do que você imagina. O pipeline de ETL horário de um cliente é um exemplo claro. No Job Classic a $0,30 por DBU, ele consumia cerca de 44 DBUs por dia, o que dava aproximadamente $13 em DBUs mais outros $10 em cobranças de VM na nuvem, cerca de $23 por dia no total. A versão serverless do mesmo workload usava menos DBUs (por volta de 38, porque escalava de forma mais justa ao trabalho real) a $0,45 por DBU, ficando em torno de $18 por dia sem nenhuma fatura de nuvem separada. A opção com a taxa nominal mais alta era a mais barata quando a cobrança de VM entrava na conta, e exigiu zero ajuste fino para chegar lá.

Há um segundo custo que nunca aparece em nenhuma das faturas: o tempo de engenharia para dimensionar e ajustar um cluster clássico direito (tipo de instância, proporção de memória por núcleo, comportamento de autoscaling e a revisão de tudo isso conforme o workload evolui). Para a maioria dos workloads, esse tempo custa mais do que qualquer sobretaxa de DBU. Um dia de ajustes para cortar 10% de um pipeline modesto pode levar um ano para se pagar. O serverless também elimina uma classe inteira de problemas operacionais: sem tempo de inicialização de cluster, sem gerenciamento de versões, sem clusters ociosos esquecidos.

Sendo honesto: o serverless raramente é a opção isoladamente mais barata para um pipeline específico, mas para a maioria dos pipelines ele cobre de 80 a 90% do caminho com zero esforço de ajuste. No seu portfólio como um todo, isso vence em custo total de propriedade, porque a vasta maioria dos seus pipelines acaba razoavelmente eficiente sem que você gaste um minuto com eles. Depois, use seu ranking de custos para encontrar o punhado de jobs de alta frequência e alto custo que rodam de forma previsível, e esses são os que valem migrar para compute clássico e ajustar à mão, incluindo a conta das VMs de nuvem. Otimize os outliers e deixe todo o resto no serverless por padrão.

Quando for configurar compute clássico, comece com o menor recurso que funciona e escale com base em evidências. O superdimensionamento é o estado padrão da maioria das implantações de Databricks, porque as configs são copiadas de um colega, herdadas de um projeto antigo ou deixadas no que a UI sugeriu. Escolha o menor tamanho de SQL Warehouse e suba apenas quando os tempos de query ficarem inaceitáveis; para clusters, comece com um tipo de nó de propósito geral e faça autoscaling de um para dois ou quatro workers. Um compute com o dobro do tamanho não roda jobs duas vezes mais rápido, mas com certeza custa o dobro.

Como impedir que os custos voltem a subir?

A otimização individual é um ponto de partida, não um estado permanente. Times crescem, workloads se multiplicam, novos engenheiros chegam com seus próprios hábitos, e os custos voltam a subir, a menos que algo os segure. Esse algo é uma camada de governança, e é ela que transforma uma limpeza pontual em uma base duradoura.

A medida isolada mais confiável é parar de permitir a criação ad hoc de compute. Quando engenheiros provisionam seus próprios clusters, as configurações que importam (auto-termination, limites de escala, tipos de instância, tags) são definidas de forma inconsistente, ou nem são, e toda otimização cuidadosa feita em outro lugar vaza. Defina seus clusters e warehouses como infraestrutura como código, implante-os via CI/CD e faça com que os engenheiros escolham de um conjunto pré-aprovado em vez de construir o próprio. Para os usuários avançados que realmente precisam criar compute customizado, as cluster policies são o meio-termo: uma policy pode impor auto-termination, limitar o tamanho do cluster e restringir tipos de instância, deixando espaço para ajustes dentro desses limites. A opção mais econômica passa a ser a única disponível. Para saber mais sobre por que achamos que esse problema merece ferramentas dedicadas, veja por que construímos o SELECT para Databricks.

A prevenção não pega tudo, então combine-a com alertas. O Databricks tem um recurso nativo de budgets no console da conta para limites de gastos, o que é um bom ponto de partida. Mas o sinal mais sensível é estatístico, não um limite fixo: meça o desvio padrão do custo diário ou semanal por workload e alerte quando sair da faixa normal. Um limite fixo só dispara depois que o gasto já cruzou um limite rígido. Monitorar o desvio pega o problema no dia em que um job começa a se comportar mal, não no fim do ciclo de faturamento, quando o estrago já está feito. Essa visibilidade no mesmo dia é a diferença entre uma pequena correção e uma fatura feia.

A otimização de custos do Databricks não é um projeto pontual. A plataforma evolui, os times adicionam workloads, e a base que você trabalhou para baixar vai voltar a subir sem visibilidade contínua. O SELECT dá aos times de plataforma de dados essa visibilidade em um só lugar, ranqueando gastos por workload, pegando desvios assim que começam e revelando as economias que se acumulam ao longo do tempo. Agende uma demo para ver o que ele revela no seu ambiente.

FAQ

Qual é a forma mais rápida de reduzir custos do Databricks?

Duas mudanças de configuração recuperam mais dinheiro com menos esforço: configure auto-termination em todo cluster e SQL Warehouse para que recursos ociosos parem de ser cobrados, e mova pipelines agendados do compute all-purpose para o Jobs Compute. No Azure Premium, isso muda um job de $0,55 por DBU para $0,30, um corte de cerca de 45% na taxa daquele workload. Ambas podem ser feitas em uma tarde. A ressalva honesta: nenhuma das duas toca um pipeline mal desenhado. Se um job reprocessa todo o seu histórico toda noite ou escaneia muito mais dados do que retorna, ele continua caro no cluster mais barato e corretamente dimensionado que você puder dar a ele. Os ganhos rápidos estabelecem uma base mais baixa; baixá-la ainda mais significa redesenhar o trabalho.

Serverless é mais barato que o compute clássico?

Não por DBU, e nem sempre no total, então não há um sim ou não simples. O serverless tem uma taxa mais alta (no Azure Premium, $0,45 por DBU no Jobs Serverless contra $0,30 no Jobs Classic), mas embute a infraestrutura que você pagaria e ajustaria por conta própria. Para a maioria dos workloads, o tempo de engenharia economizado supera a diferença na taxa, e é por isso que o serverless é um bom padrão. A armadilha a observar: o serverless escala com tanta suavidade que os aumentos de custo se escondem melhor do que no compute clássico. Duas execuções podem ter a mesma duração no relógio consumindo quantidades de DBU bem diferentes, porque o serverless escalou silenciosamente para a mais pesada. A duração parece estável enquanto a fatura dobra. Monitore o consumo de DBUs, não apenas o tempo de execução.

O Unity Catalog aumenta minha fatura do Databricks?

O Unity Catalog em si não é um produto com preço separado, mas habilitá-lo muda seu perfil de custos de formas que vale a pena entender antes de migrar. O Predictive Optimization, que executa OPTIMIZE e VACUUM automaticamente em tabelas gerenciadas do Unity Catalog, consome DBUs (em geral ele se paga com a economia nas queries, mas é um item de custo real). Recursos de governança, manutenção de tabelas gerenciadas e o compute serverless em que várias operações de catálogo rodam aparecem em algum lugar da conta. Cobrimos como o Unity Catalog afeta os custos em um guia próprio; a versão curta é que governança vale a pena, mas não é de graça, e você deveria saber onde ela entra na fatura antes de ativá-la.