27 pontos por GN⁺ 2025-12-03 | 2 comentários | Compartilhar no WhatsApp
  • A estrutura de gravador único e a natureza embarcada do SQLite foram comprovadas experimentalmente como fatores que, na prática, aumentam escalabilidade e desempenho
  • Nas mesmas condições, o Postgres caiu para 348 TPS com latência de rede, enquanto o SQLite, ao eliminar a rede, alcançou 44.096 TPS
  • Com processamento em lote e transações granularizadas com base em SAVEPOINT, aproveitando o modelo de gravador único, registrou até 186.157 TPS e, em uma configuração estável, 102.545 TPS
  • A Lei de Amdahl explica os gargalos dos bancos de dados baseados em rede, e o SQLite mantém alta eficiência justamente por evitá-los
  • O resultado destaca o potencial do SQLite em ambientes locais e a importância de eliminar gargalos de rede

Estrutura do SQLite e ambiente experimental

  • O SQLite não tem MVCC e permite apenas um gravador, mas essa estrutura acaba possibilitando alta escalabilidade
    • Como banco de dados embarcado, não há sobrecarga de rede
  • O benchmark foi executado em um MacBook Pro (2021) com Apple M1 Pro e 16 GB de memória
  • O experimento não buscou uma otimização perfeita, mas sim mostrar que é possível alcançar alta taxa de escrita mesmo em condições comuns

Definição de TPS e exemplo de transação

  • TPS não significa apenas velocidade bruta de escrita, mas sim transações interativas (Interactive Transaction)
    • Ex.: em uma transferência entre contas, várias consultas e código da aplicação são executados dentro de uma única transação
  • Como a transação pode reverter o estado em caso de erro, ela tem papel central na manutenção da consistência

Configuração do benchmark

  • Foram usadas virtual threads baseadas em Clojure para simular um grande volume de requisições simultâneas
  • O Postgres foi configurado com pool de conexões baseado em HikariCP, enquanto o SQLite usou um único gravador e conexões de leitura equivalentes ao número de núcleos
  • Ambos os bancos usaram uma tabela account simples com os campos id, balance, inserindo 1 bilhão de linhas
  • A atividade dos usuários segue uma distribuição de lei de potência (0.9995), com cerca de 100 mil usuários ativos

Desempenho do banco de dados em rede (Postgres)

  • No mesmo servidor, o Postgres atingiu 13.756 TPS
  • Ao adicionar 5 ms de latência de rede, caiu para 1.214 TPS; com 10 ms, para 702 TPS
  • Após aplicar nível de isolamento serializável, caiu para 660 TPS e, com consultas adicionais, para 348 TPS
  • Isso mostra, de acordo com a Lei de Amdahl, que o gargalo de rede limita o desempenho total
    • À medida que a latência de rede aumenta, a contenção por locks de transação se intensifica e a escalabilidade desaparece

Vantagens do SQLite como embarcado

  • Ao remover a rede, o SQLite alcançou 44.096 TPS
    • Com o gargalo de rede eliminado, o impacto da Lei de Amdahl é minimizado
  • Aplicando processamento em lote (batch processing) e explorando a estrutura de gravador único, o desempenho subiu para 186.157 TPS
    • O ajuste dinâmico do tamanho do lote otimiza automaticamente latência (latency) e vazão (throughput)

Transações granularizadas com SAVEPOINT

  • Para evitar que falhas em transações individuais afetem o lote inteiro, foram aplicadas transações aninhadas com SAVEPOINT
    • Em caso de falha, apenas aquela transação é revertida, e o lote inteiro é preservado
  • Mesmo assim, o sistema manteve 121.922 TPS

Teste de carga mista de leitura/escrita

  • A carga foi composta por 75% de leituras e 25% de escritas
  • Foi usado um pool separado de threads de leitura para isolar as leituras, impedindo que afetassem as escritas
  • Como resultado, foram alcançados 102.545 TPS

Resumo da comparação de desempenho

Condição Postgres SQLite
Sem rede 13.756 44.096
Latência de 5 ms 1.214 n/a
Latência de 10 ms 702 n/a
10 ms + serialização 660 n/a
Processamento em lote n/a 186.157
Lote + SAVEPOINT n/a 121.922
Lote + SAVEPOINT + leitura n/a 102.545

Conclusão

  • O SQLite alcança TPS muito mais altos que bancos de dados baseados em rede graças ao modelo de gravador único e à estrutura embarcada
  • Ao evitar os limites de gargalo de rede apontados pela Lei de Amdahl, ele maximiza a eficiência
  • Todo o código foi publicado no GitHub, e também foram apresentados materiais relacionados sobre Lei de Amdahl, lei de potência e casos de escalabilidade com SQLite
  • O SQLite é uma opção altamente eficaz para processamento transacional de alto desempenho em ambientes locais

2 comentários

 
ppp123 2025-12-10

Então, se for usar só em ambiente local sem recorrer a servidores externos, a ideia é que não há necessidade de pagar o imposto da rede. (VFS vs Socket)

 
GN⁺ 2025-12-03
Opinião no Hacker News
  • Estou criando um servidor ORM/CRUD híbrido com protobuf baseado em SQLite
    O código e a explicação estão em GitHub - accretional/collector
    Com backup em tempo real, é possível ter 5~15ms de indisponibilidade, enfileirar centenas de solicitações de leitura/escrita, latência total de CRUD na casa de 1ms e até backup por streaming com base em WAL
    Antes eu só usava Postgres e Spanner, mas se o Collector ganhar apenas um recurso de particionamento, acho que não volto a usar Postgres

    • Fico curioso se você já considerou fazer backup com zero downtime usando SQLite + WAL em um sistema de arquivos com snapshot atômico como o BTRFS. Basta tirar o snapshot, fazer o backup com calma e depois apagá-lo
  • A desvantagem é que todos os dados e operações precisam caber em uma única máquina
    Com uma instância AWS u-24tb1.112xlarge (448 vcores, 24TB de RAM, 64TB de EBS), há bastante folga

    • Mas, se você alugar um servidor bare metal da Hetzner, o desempenho por núcleo é 2 a 3 vezes melhor, com 90% de redução no custo
    • A dimensão máxima teórica do banco no SQLite é de 281TB, como consta na documentação oficial. Na prática, o limite do sistema de arquivos é menor, mas funciona normalmente
    • Escalar verticalmente em uma única máquina é estável, mas tem pouca elasticidade. Em picos de tráfego, você precisa superprovisionar ou aceitar falhas
    • Vendo o link yourdatafitsinram.net, que pergunta “seus dados cabem na RAM?”, acho que, para um único nó de alto desempenho, um servidor dedicado faz mais sentido do que EC2
  • O texto enfatiza a eficiência do SQLite, mas sinto que o critério de comparação não está claro
    Isso porque ele parte de uma arquitetura originalmente separada em servidores e depois mede o desempenho de um banco embarcado local
    Nas mesmas condições, um Postgres local bem ajustado também pode entregar desempenho parecido

    • SQLite é mais rápido do que Postgres na mesma máquina. Faz sentido testar com base na configuração usada na implantação real
    • Você também pode colocar o SQLite atrás de um handler de requisições e executá-lo em outro servidor. No fim, um banco é apenas a combinação de processador de requisições e armazenamento
    • Em uma única máquina, o que importa é o throughput bruto. SQLite é 10 vezes mais rápido que PG, e o PG fica mais lento quanto maior for a complexidade da transação
    • Dizer “então o SQLite não é um comparável” é simplificar demais. O texto ficaria curto demais
    • SQLite serve não só para mobile ou embarcados, mas também para aplicações de servidor com baixa concorrência. Não é um banco só para servidores web
  • Limitar o número de conexões do Postgres a 8 pode ser um gargalo
    Seria bom divulgar também o uso de CPU e threads e refazer o teste com um pool de conexões maior

    • Ajustar o pool de conexões para bater com o número de núcleos (8) faz sentido, mas, se houver sleep dentro da transação, isso pode criar gargalo
      Se aumentar para 64 conexões, o throughput pode subir 8 vezes. É preciso ampliar a configuração do cliente até atingir o limite
    • É difícil acreditar nesses números deste texto. Eu consigo TPS bem mais alto até com MySQL baseado em rede
  • O ponto principal é reconhecer se a latência de rede é o gargalo
    Em muitas cargas de trabalho, um banco local comum é mais rápido que um ótimo banco remoto
    O importante não é “qual banco é o melhor”, e sim “há necessidade de atravessar a fronteira da rede?

    • (autor) Exato. Não era uma discussão SQLite vs Postgres, e sim uma tentativa de tratar dos limites dos bancos baseados em rede
    • Claro, se você colocar tudo em memória e usar Redis ou Memcache, o desempenho sobe facilmente. Mas aí as regras mudam
  • Bancos de dados em rede têm a vantagem de facilitar o redeploy da aplicação
    Dá para subir uma nova instância e encerrar a antiga, possibilitando um deploy quase sem downtime
    Se o SQLite estiver na mesma instância, é preciso subir o banco de novo na hora da troca, o que complica mais. Fico curioso se você já enfrentou esse problema em produção

    • Para usar SQLite em produção, é preciso armazenamento persistente e NVMe. Em geral, ele roda em um único servidor bare metal
      Durante migrações, pode haver downtime. Graças ao Litestream, replicação e backup ficaram mais fáceis agora
    • SQLite oferece suporte a acesso multiprocessos, então também dá para fazer uma troca sem downtime subindo um novo processo e encerrando o antigo
  • O autor configurou PRAGMA synchronous="normal", o que significa que não faz fsync a cada vez
    Para uma comparação justa, deveria usar "full"

    • Mas, no modo WAL, "normal" também é aceitável. Em caso de queda de energia, perde-se durabilidade, mas a consistência da transação é mantida
  • Fico curioso sobre como seria uma configuração de HA (alta disponibilidade) para SQLite
    No mínimo, deveria ser algo com failover automático

    • Como o SQLite é uma biblioteca em C, ele pode ser estendido com projetos como rqlite, litestream e litefs
      No momento, estou em dúvida entre Postgres e SQLite (incluindo litestream).
      Meu app tolera um pouco de downtime, então escalar verticalmente em uma única máquina é mais simples e barato
    • Recentemente, um projeto multimaster chamado Marmot voltou à ativa após 2 anos.
      O Marmot no GitHub recebeu um novo mecanismo de replicação baseado em gossip
  • Fico curioso se existem casos reais em que o SQLite foi levado ao limite em produção

  • Em webapps comuns ou ambientes de e-commerce, fico curioso sobre qual seria o limite de usuários entre SQLite e Postgres
    Com atualizações recentes, o SQLite permite leituras simultâneas, mas ainda só aceita uma única escrita
    Queria saber em que casos isso vira problema e se, pensando em escalar, não seria melhor começar logo com Postgres