Ir para o conteúdo principal
Lakebase

Um guia prático para otimização de custos com o Lakebase Postgres

por Benjamin Nwokeleme, Firas Farah e Jen Darrouzet

  • O Lakebase é econômico por design porque sua arquitetura de armazenamento e computação separada permite que ramificações, réplicas de leitura e alta disponibilidade compartilhem uma única camada de armazenamento, enquanto o escalonamento automático serverless e a escala para zero significam que você paga apenas pela computação que realmente usa.
  • A maior economia prática vem da sincronização de apenas o subconjunto de trabalho dos dados do Lakehouse no Lakebase, combinando seu modo de sincronização (Snapshot, Triggered ou Continuous) com a real necessidade de atualização dos dados, e do dimensionamento correto da computação para que seu conjunto de trabalho ativo caiba no cache.
  • A aplicação dessas práticas — sincronizar apenas o conjunto de trabalho, combinar o modo de sincronização com as necessidades de atualização, dimensionar corretamente da computação para que os dados ativos caibam no cache e ajustar o PITR e os snapshots — mantém os custos previsíveis e baixos, sem abrir mão do desempenho, da disponibilidade e da experiência do desenvolvedor que suas aplicações exigem.

O Lakebase é um banco de dados Postgres totalmente gerenciado, desenvolvido para as realidades operacionais do desenvolvimento de aplicativos modernos. O que o diferencia de outros fornecedores de bancos de dados no mercado que também oferecem um mecanismo Postgres é a arquitetura subjacente, com armazenamento e computação separados por meio de uma camada de computação serverless, além de sua forte integração com o Lakehouse e a plataforma de inteligência de dados. Você pode ler mais sobre essa arquitetura e alguns dos benefícios aqui. No entanto, um benefício que costuma passar despercebido é que essa arquitetura também torna o Lakebase altamente eficiente em termos de custos. Neste blog, vamos detalhar de onde vêm essas eficiências de custo e compartilhar dicas práticas para aproveitá-las ao máximo.

Como o Lakebase é eficiente em termos de custos por design

Evite custos duplicados de armazenamento com branching

Os branches de banco de dados permitem que os desenvolvedores criem ambientes isolados com dados de produção para fins de desenvolvimento, teste ou experimentação. Ao contrário das abordagens que exigem a criação de uma cópia física separada do banco de dados para cada ambiente, os branches do Lakebase compartilham o mesmo armazenamento subjacente e rastreiam as alterações à medida que o branch diverge de seu pai. Isso torna o branching particularmente eficiente em termos de custos para ambientes de desenvolvimento e teste de curta duração, onde as equipes podem trabalhar com dados semelhantes aos de produção sem a necessidade de provisionar e manter uma cópia totalmente separada do banco de dados.

Pague apenas pela computação que usar

O Autoscaling altera ativamente os recursos de computação da sua instância do Lakebase em resposta a níveis variados de atividade. Você pode controlar o intervalo mínimo e máximo entre os quais a instância pode ser dimensionada. Os benefícios de custo desse recurso são claros: a capacidade de computação pode ser dimensionada de acordo com a demanda da carga de trabalho, em vez de ser provisionada estaticamente para o pico de uso.

Definir um tamanho máximo de computação ajuda a tornar os custos previsíveis, pois você evita gastos inesperados ao limitar o limite superior dos seus custos de computação. Durante momentos de baixo uso, sua computação reduz a escala (scales down), diminuindo os custos. Quando combinado com a escala para zero (scale to zero), a computação é totalmente suspensa após um período de inatividade, reduzindo os custos de computação a zero. A computação é retomada a partir da escala para zero em algumas centenas de milissegundos. Isso a torna especialmente atraente para cenários que não são excepcionalmente sensíveis à latência, como fluxos de trabalho de desenvolvimento, variantes de aplicativos que não são de produção e aplicativos de produção que não exigem latências de dois dígitos.

Quando a escala para zero está desativada, o Lakebase tem o preço sempre ativo (always on pricing), que oferece um desconto de 25% na sua capacidade de linha de base. Essa redução de custo também se aplica a qualquer computação que não possa ser dimensionada para zero, como configurações de HA.

Adicione réplicas e alta disponibilidade sem duplicar o armazenamento

A separação de armazenamento e computação do Lakebase também torna as réplicas de leitura e a alta disponibilidade mais eficientes em termos de custos. As réplicas de leitura são instâncias de computação independentes que leem da mesma camada de armazenamento subjacente que a primária, portanto, dimensionar a capacidade de leitura não exige a criação e o pagamento de outra cópia do banco de dados. Da mesma forma, a alta disponibilidade adiciona computação redundante em zonas de disponibilidade, enquanto continua a usar a camada de armazenamento altamente disponível existente. Isso significa que você pode adicionar escala de leitura e redundância de computação sem multiplicar seu consumo de armazenamento.

Dicas práticas para otimizar os custos do Lakebase

Sirva um subconjunto de dados do Lakehouse com as Synced Tables do Lakebase

A forte integração do Lakebase com a Databricks Intelligence Platform mais ampla permite sincronizações gerenciadas entre os dois ambientes. As tabelas sincronizadas expõem dados do Unity Catalog no seu banco de dados Lakebase para dar suporte a leituras transacionais de baixa latência para casos de uso de aplicativos ou fornecimento de recursos (feature-serving).

Um erro comum que os clientes cometem é enviar uma grande tabela Delta para o Lakebase quando o aplicativo consulta apenas um subconjunto ativo muito menor. Isso infla o armazenamento do Lakebase, aumenta os custos de sincronização e pode até levar a problemas de desempenho em alguns cenários. A solução é simples: sincronize apenas o conjunto de trabalho (working set) necessário para o aplicativo. Defina exatamente os dados de que seu aplicativo precisa com uma Materialized View, por exemplo, uma janela móvel de 60 dias, e sincronize apenas isso. Os pipelines de sincronização do Lakebase podem usar o change data feed automático da MV para computar alterações no nível da linha no momento da leitura. Isso significa que as alterações na MV, incluindo exclusões à medida que as linhas expiram de uma janela móvel, podem ser propagadas de forma incremental para o Lakebase. O resultado é um subconjunto ativo atualizado e de baixa latência no Lakebase, enquanto o histórico completo permanece no Delta. Combine isso com o modo de sincronização mais enxuto que atenda aos seus requisitos, abordado abaixo, e você terá um padrão de ETL reverso muito mais eficiente em termos de custos.

Usando o modo de sincronização adequado de Lakehouse → Lakebase

As Synced Tables são Serverless Spark Declarative Pipelines (SDP) gerenciados nos bastidores e são executados durante a sincronização. Consequentemente, o custo de sincronização é impulsionado por fatores como a quantidade de dados que estão sendo movidos e o tamanho da instância do Lakebase / Unidades de Capacidade (CUs).

Existem três modos de sincronização diferentes para mover dados do Lakehouse para o Lakebase, e é importante alinhar o modo com o nível de atualização que os dados realmente precisam ter. Escolher o modo certo permite que você atenda aos seus requisitos de latência enquanto mantém os custos sob controle.

ModoDescriçãoMelhor usar quando
SnapshotCópia de todos os dadosAs alterações na origem são >10% das linhas por ciclo. Será substancialmente mais econômico do que o modo Triggered nesses cenários.
TriggeredAtualizações incrementais que são executadas sob demanda ou em intervalosAs linhas de origem mudam em uma cadência conhecida. Inserções, atualizações e exclusões são propagadas a cada atualização.
ContinuousStreaming em tempo real com segundos de latênciaAs alterações devem aparecer no Lakebase quase em tempo real. Isso oferece a menor latência com o maior custo.

Origem: Modos de Sincronização

O Snapshot é a opção mais econômica para tabelas atualizadas com pouca frequência ou altamente voláteis, enquanto o Continuous pode ser o mais caro porque seu pipeline é executado continuamente e consome computação mesmo quando não há alterações para processar. O modo Snapshot é recomendado quando mais de 10% dos dados de origem mudam entre as sincronizações, pois pode ser até 10 vezes mais eficiente. Para cargas de trabalho incrementais, o modo Triggered oferece o equilíbrio ideal entre custo e latência. Você pode obter uma atualização quase contínua com economia combinando o modo Triggered com um gatilho de atualização de tabela (table-update trigger), garantindo que ele seja executado apenas quando os dados de origem forem alterados. Em geral, evite intervalos longos entre as execuções, pois um acúmulo massivo de alterações pode tornar a sincronização subsequente lenta e cara.

Outra otimização de custo útil é a capacidade de fazer binpack, ou agrupar, várias tabelas em um único pipeline de sincronização. Se o seu caso de uso permitir, o mesmo pipeline pode sincronizar alterações de várias tabelas Delta para o Lakebase, permitindo que essas tabelas compartilhem a mesma computação subjacente. Isso pode ser particularmente valioso para sincronizações do tipo Continuous, onde o pipeline está sempre em execução, pois evita pagar por pipelines separados em execução contínua para cada tabela.

Dimensione corretamente o Lakebase desde o início

Quando um projeto do Lakebase é criado, ele vem automaticamente com um branch de produção e uma computação primária de leitura e gravação. Por padrão, essa computação é configurada para realizar o autoscale entre 8 e 16 CU, com a escala para zero ativada após 24 horas de inatividade. Esses padrões podem ser perfeitamente razoáveis para sua carga de trabalho, mas se seu aplicativo exigir menos computação, deixá-los inalterados pode significar pagar por mais capacidade do que o necessário.

Em vez de criar o projeto e lembrar de redimensioná-lo depois, você pode definir o intervalo de computação inicial ao provisionar o projeto de forma programática. For exemplo, usando o Databricks SDK:

Se você gerencia o Lakebase de forma declarativa com os Declarative Automation Bundles (DABs), você pode definir de forma semelhante o intervalo de computação para os endpoints que provisiona:

O fator mais importante para o dimensionamento é o seu working set: os dados e índices que seu aplicativo acessa com frequência, em oposição ao tamanho total do seu banco de dados no disco. Um banco de dados de 2500 GB com um working set ativo de 20 GB não precisa de 2500 GB de RAM. Ele só precisa de memória suficiente para manter esses 20 GB em cache, mais uma margem adicional. Isso é importante devido à forma como o recurso de computação utiliza a memória. A RAM escala linearmente com o tamanho do recurso de computação, e até 75% da RAM de um recurso de computação está disponível como seu cache de computação. Quando o seu working set cabe nesse cache, a grande maioria das leituras é atendida a partir da memória, de modo que elas continuam rápidas e sua latência permanece consistente. Quando não cabe, o Postgres precisa buscar no armazenamento as páginas que não estão no cache (cache misses), o que é muito mais lento do que um acesso à memória (memory hit) e introduz a variabilidade de latência que seu aplicativo sentirá. Portanto, o dimensionamento consiste basicamente em escolher um recurso de computação cujo cache exceda o seu working set, deixando também uma margem para outras operações. No entanto, a memória não é a única coisa que escala com o tamanho do recurso de computação. Considere também a complexidade das consultas, a concorrência e suas metas de latência, pois uma carga de trabalho altamente concorrente ou sensível à latência precisa de mais margem do que uma ferramenta interna pouco usada com o mesmo tamanho de dados.

As conexões com o banco de dados também merecem atenção especial. O max_connections, o limite máximo para conexões simultâneas do Postgres, também é determinado pelo tamanho do seu recurso de computação e, para uma computação com escalonamento automático (autoscaling), segue uma regra específica: o limite é definido pelo menor valor entre o seu CU máximo e oito vezes o seu CU mínimo. Portanto, aumentar o máximo adiciona conexões apenas até oito vezes o seu mínimo e, além desse ponto, um mínimo pequeno limita até onde um máximo maior pode levar você. Um aplicativo que abre um grande número de conexões pode atingir esse limite e começar a rejeitar novas conexões com erros. Se o volume de conexões for uma restrição real, leve isso em consideração no seu CU mínimo e coloque um pooler de conexões na frente do Lakebase. Um pooler permite que muitas conexões de clientes compartilhem um pool de conexões do Postgres e suporta até 10.000 conexões de clientes simultâneas. O pooling geralmente é a resposta certa para aplicativos que abrem muitas conexões e é mais barato do que redimensionar a computação apenas para aumentar o limite de conexões.

Você não precisa adivinhar nada disso. O painel de métricas do Lakebase relata o tamanho do seu working set em janelas de 5 minutos, 15 minutos e 1 hora e o exibe diretamente ao lado do cache de computação disponível, para que você possa ver rapidamente se seus dados ativos cabem. Analise-o junto com a taxa de acerto do cache (cache hit rate), utilização de CPU, RAM e conexões para validar seu dimensionamento inicial e ajustá-lo para mais ou para menos. Para cargas de trabalho com padrões de acesso estáveis, comparar o working set de 1 hora com o cache de computação disponível é um sinal particularmente útil. O escalonamento automático (autoscaling) oferece o maior benefício quando seu working set já cabe na memória no CU mínimo, pois, caso contrário, você pagará uma penalidade de cache frio (cold cache) toda vez que a computação for dimensionada para cima. Use essas métricas para definir um mínimo que comporte seu working set e um máximo que absorva seus picos.

Como é a sensação de um recurso de computação subdimensionado

O subdimensionamento raramente se manifesta como uma falha total. Na maioria das vezes, ele aparece como sintomas fáceis de diagnosticar incorretamente:

  • Latência de consulta lenta e inconsistente. Quando o working set não cabe mais no cache, as leituras que não encontram o cache vão para o armazenamento. Sua latência mediana ainda pode parecer boa, enquanto o p95 e o p99 aumentam e se tornam erráticos, pois o desempenho agora depende se os dados de uma determinada consulta estavam no cache.
  • Uma queda na taxa de acerto do cache (cache hit ratio). Este é o principal indicador de que seu working set superou o cache disponível, e ele começa a cair antes que a latência piore visivelmente.
  • Saturação de CPU e enfileiramento de consultas. Um recurso de computação subdimensionado sobrecarrega a CPU sob carga, fazendo com que as consultas esperem, o rendimento (throughput) se estabilize e a latência aumente de forma geral.
  • Erros de conexão. Cada tamanho de computação tem um limite para conexões simultâneas; quando os clientes o excedem, as novas conexões são rejeitadas com erros de "muitos clientes" (too many clients), em vez de apresentar uma degradação gradual.
  • Uma penalidade de cache frio (cold cache) após o escalonamento ou ativação. Após uma ativação a partir do zero (scale-to-zero) ou quando o escalonamento automático aumenta pela primeira vez, o cache começa vazio e precisa ser aquecido. Você verá um pico de consultas mais lentas até que o working set seja armazenado em cache novamente, e é por isso que o tamanho mínimo da computação importa tanto quanto o máximo.

Otimize sua estratégia de PITR e Snapshot

A restauração de ponto no tempo (PITR) mantém continuamente o histórico necessário para restaurar seu banco de dados para qualquer momento dentro de uma janela de recuperação configurável de 2 a 30 dias. Os snapshots, por outro lado, são capturas discretas de um ponto no tempo de uma ramificação raiz (root branch) que podem ser criadas manualmente ou em uma programação automatizada diária, semanal ou mensal.

O armazenamento de PITR cresce tanto com a atividade de gravação quanto com a duração da sua janela de recuperação, já que o Lakebase deve reter o histórico de alterações durante esse período. Para um aplicativo com muitas gravações, uma janela longa de PITR pode resultar em um consumo significativo de armazenamento. Uma abordagem consciente dos custos é escolher uma janela de PITR que atenda aos seus requisitos de recuperação de incidentes e complementá-la com snapshots agendados quando precisar de pontos de recuperação de longo prazo.

A boa notícia é que ambos têm preços mais baixos do que o armazenamento regular de ramificação (branch) do Lakebase. O armazenamento de snapshot (US$ 0,090/GB-mês) é cerca de 74% mais barato do que o armazenamento regular de ramificação, enquanto o armazenamento de PITR (US$ 0,200/GB-mês) é cerca de 42% mais barato. Os snapshots agendados podem ser particularmente eficientes em termos de armazenamento: o primeiro snapshot de um cronograma é armazenado como um snapshot completo, enquanto os snapshots subsequentes são cobrados apenas pelas alterações incrementais.

Use o PITR para se recuperar de incidentes inesperados, como exclusões acidentais ou gravações incorretas que possam ocorrer a qualquer momento dentro da sua janela de recuperação. Use snapshots para pontos de recuperação planejados. For example, tire um snapshot manual antes de uma migração arriscada ou atualização em lote, e use snapshots agendados para proteção rotineira de longo prazo.

Por fim, alinhe sua configuração de recuperação aos seus requisitos reais de recuperação. Manter mais histórico ou pontos de recuperação do que o necessário pode aumentar os custos de armazenamento sem fornecer um valor adicional significativo.

Como encontrar seus custos do Lakebase

Como discutido acima, os custos do Lakebase se dividem em três áreas: computação do banco de dados, armazenamento do banco de dados e, ao usar Synced Tables, a computação de pipeline sem servidor (serverless) usada para sincronizar dados do Lakehouse para o Lakebase.

Computação é medida com base no uso de CU ao longo do tempo. Com o escalonamento automático (Autoscaling), o uso acompanha a capacidade de computação consumida à medida que o banco de dados é dimensionado dentro do intervalo configurado.

Armazenamento inclui o armazenamento de ramificação do banco de dados, o histórico de restauração de ponto no tempo (PITR) e o armazenamento de snapshot. Eles são medidos separadamente com base no uso de armazenamento subjacente.

Synced Tables usam pipelines gerenciados para mover dados do Unity Catalog para o Lakebase. A computação de pipeline usada para a sincronização é faturada separadamente da computação do banco de dados Lakebase.

Visualizar custos de computação e armazenamento do Lakebase

O uso de computação e armazenamento do Lakebase está disponível em system.billing.usage. O uso de armazenamento pode ser detalhado ainda mais usando product_features.lakebase.storage_type:

  • BRANCH_DATA_STORAGE: armazenamento para ramificações de banco de dados que não expiram
  • BRANCH_CHANGE_STORAGE: dados alterados armazenados para ramificações que expiram
  • BRANCH_HISTORY_STORAGE: histórico retido para PITR

A consulta abaixo une usage a system.billing.list_prices para estimar o custo diário com base no preço de tabela vigente.

O Lakebase expõe SKUs de computação e armazenamento separados em tabelas de faturamento do sistema, com o campo de tipo de armazenamento fornecendo o detalhamento adicional mostrado acima.

Você pode encontrar o UID do projeto na interface do Lakebase em Project > Settings > UID. Programaticamente, se souber o nome do projeto, liste os projetos e faça a correspondência em status.display_name para recuperar seu UID.

Visualizar custos de pipeline de Synced Table

O uso do pipeline de Synced Table também pode ser consultado em system.billing.usage. Filtre pelo ID do pipeline subjacente e faça join com system.billing.list_prices para estimar o custo diário do pipeline.

Essas consultas estimam o custo usando o preço de tabela vigente para o período de uso. Descontos contratuais específicos do cliente não são refletidos.

Você pode encontrar o ID do pipeline abrindo a Synced Table na interface e copiando o Pipeline ID. Programaticamente, recupere a Synced Table e leia status.pipeline_id:

Juntando tudo

O Lakebase foi projetado para ser econômico desde a sua arquitetura, desde o armazenamento compartilhado e ramificação até autoscaling e computação serverless. Combine essas eficiências integradas com uma configuração bem planejada de dimensionamento, estratégia de sincronização e recuperação, e você poderá manter os custos previsíveis, obtendo o desempenho, a disponibilidade e a experiência de desenvolvimento que seus aplicativos precisam.

(Esta publicação no blog foi traduzida utilizando ferramentas baseadas em inteligência artificial) Publicação original

Receba os posts mais recentes na sua caixa de entrada

Assine nosso blog e receba os posts mais recentes diretamente na sua caixa de entrada.