🚀 Oferta especial: 60% OFF no CrazyStack - Últimas vagas!Garantir vaga →
Banco de Dados

Paginação Offset vs Cursor: Performance e Melhores Práticas no SQL

Descubra as diferenças e impactos reais das estratégias Offset-based e Cursor-based Pagination para bases de dados grandes. Aprenda como escolher a abordagem ideal em cada cenário e melhore a performance das suas queries.

CrazyStack
15 min de leitura
paginação sqloffset vs cursorperformance banco de dadosscroll infinito

Por que isso é importante

Uma implementação inadequada de paginação pode tornar grandes sistemas lentos, consumir recursos além do necessário e afetar negativamente a experiência do usuário. Escolher entre Offset-Based Pagination e Cursor-Based Pagination impacta diretamente performance, escalabilidade e custos de bancos de dados em aplicações modernas.

O que é Offset-Based Pagination?

O modelo Offset-Based Pagination utiliza os comandos OFFSET e LIMIT nas queries para retornar apenas um subconjunto de registros, permitindo navegar entre "páginas" de dados com facilidade. Por exemplo, ao consultar a página 2 com 10 itens por página, você faz OFFSET 10 LIMIT 10, pulando os 10 primeiros e pegando os próximos 10 resultados.

ℹ️Atenção

Apesar de ser simples e bastante utilizado, o OFFSET não reduz a quantidade de registros consultados internamente pelo banco – apenas os registros retornados para o cliente.

Por que o OFFSET traz problemas de performance?

Quando se trabalha com tabelas que possuem milhões de registros, o banco precisa percorrer (e processar) todos os registros até o número do OFFSET antes de retornar o resultado solicitado. Isso faz com que consultas em páginas distantes da primeira aumentem exponencialmente em tempo de execução e uso de memória, tornando o processo cada vez mais lento e custoso.

⚠️Atenção

Em cenários de paginação profunda (ex: OFFSET 1.000.000), o banco pode demorar vários segundos para responder e gerar alto consumo de CPU e RAM, afetando outros processos e a saúde do sistema como um todo.

Comportamento Interno do OFFSET no SQL

Diferente do WHERE, que filtra registros logo no início da execução da query, o OFFSET apenas pula os resultados já processados. Isso significa que, para OFFSET 500 LIMIT 20, o banco busca os 520 registros e só retorna os 20 após o 500º, ao invés de simplesmente limitar a consulta desde o começo.

Atenção

OFFSET não indica ao banco de dados quais linhas exatamente ignorar em relação à ordenação do resultado, pois o banco não guarda referência sequencial dos registros consultados.

Quando usar Offset-Based Pagination de forma segura

Offset-Based Pagination é suficiente e eficiente quando você trabalha com um volume pequeno ou moderado de dados (centenas a poucos milhares de registros), onde o overhead de ignorar múltiplos registros não afeta significativamente o desempenho. Também é útil quando a navegação direta entre páginas exatas é importante para o usuário.

1
Passo 1: Analise o tamanho máximo da sua tabela antes de optar por OFFSET.
2
Passo 2: Considere a necessidade de navegação direta entre páginas.
3
Passo 3: Utilize índices para garantir que o ORDER BY acompanhe o OFFSET de modo eficiente.

Paginação com Scroll Infinito: o que muda?

Em interfaces modernas, cada vez mais comuns são as listas com carregamento contínuo (scroll infinito), como exemplos do Twitter e Instagram. Nesses casos, o usuário não seleciona páginas, mas carrega os itens seguintes conforme rola a tela. Aqui, a abordagem com OFFSET rapidamente se torna ineficiente.

Entrada do Cursor-Based Pagination

Cursor-Based Pagination utiliza um campo ordenável do registro (ex: ID sequencial ou data de publicação) como referência para buscar novos elementos, usando um WHERE ao invés de OFFSET. Assim, ao buscar a próxima "página" de dados, só são buscados registros após o último exibido, aumentando a performance drasticamente, especialmente em grandes volumes.

Como funciona Cursor-Based Pagination

Em vez de pular um número fixo de registros, você envia o valor do último campo ordenável exibido (como o ID ou data) como cursor para a próxima consulta. Por exemplo, WHERE id > 400, LIMIT 20. Assim, só os registros após o último são trazidos, sem custo extra de leitura de dados.

1
Passo 1: Escolha um campo único e ordenável da sua tabela.
2
Passo 2: Use o valor do último item retornado em cada carregamento como cursor para a próxima busca.
3
Passo 3: Implemente no frontend o armazenamento deste cursor ao carregar mais registros.

Limitações do Cursor-Based Pagination

Ao contrário do Offset, o Cursor-Based Pagination não permite navegação direta para qualquer página arbitrária, pois depende do último cursor recebido. Ele é ideal para fluxos contínuos como scroll infinito, mas não para cenários onde ir para a página X é fundamental.

⚠️Atenção

Cursor-Based depende de um campo ordenável confiável (ID incremental, data, número serial). Em bancos onde o identificador é um UUID v4 (sem ordenação temporal), não é possível usar essa abordagem corretamente – prefira UUID v7 ou campos com data/hora.

Desafios com IDs não ordenáveis e alternativas

Quando o campo de identificação não é sequencial (como UUID v4), o banco não consegue definir a ordem natural dos registros para Cursor-Based Pagination. Isso impede ordenar ou filtrar registros pela ordem de criação. Para casos assim, o recomendado é adotar um campo de data ou migrar para UUID v7 (ordenável por tempo).

Atenção

Não tente forçar paginação cursor por UUID v4: as páginas se tornam imprevisíveis e até inconsistentes para o usuário.

Comparando Offset-Based e Cursor-Based Pagination

Offset-Based Pagination

Paginação tradicional usando OFFSET e LIMIT para navegar por páginas exatas.

Prós
  • Permite pular para qualquer página rapidamente
  • Simples de implementar
Contras
  • Degrada progressivamente a performance com o aumento de registros
  • Alto consumo de recursos em páginas avançadas

Cursor-Based Pagination

Utiliza um campo ordenável como referência, buscando sempre a partir do elemento mais recente processado.

Prós
  • Performance estável, mesmo com milhões de registros
  • Ideal para scroll infinito e APIs modernas
Contras
  • Impossibilita navegação por página exata
  • Depende de campo ordenável confiável

Ferramentas e recursos para implementar e testar paginação

PostgreSQL Explain Analyze

Analisa planos de execução de queries e ajuda a identificar gargalos de OFFSET.

Saiba mais →

Prisma ORM

ORM moderno para Node.js com suporte a both Offset e Cursor Based Pagination.

Saiba mais →

UUID v7 Docs

Leia sobre o UUID v7 para IDs ordenáveis.

Saiba mais →

SQLite Database Browser

Ferramenta grátis para explorar pequenas bases e simular diferentes métodos de paginação.

Saiba mais →

Resumo: Escolhendo a melhor estratégia de paginação

Para aplicações e painéis onde o volume de dados é pequeno e a navegação direta por página é necessária, Offset-Based Pagination ainda é eficiente. Em APIs modernas, listas longas e scroll infinito, Cursor-Based Pagination entrega performance muito superior e estabilidade, sendo indispensável para grandes volumes de dados.

Erros comuns e como evitá-los

1
Erro 1: Usar OFFSET em tabelas com milhões de linhas sem índices robustos.
2
Erro 2: Implementar cursor em campos não ordenáveis ou não únicos.
3
Erro 3: Não considerar plano de execução de queries em ambientes de produção.

Checklist de implementação de paginação eficiente

Checklist de Implementação

Identifique o volume de registros envolvidos na listagem por tabela
Avalie se a experiência exige navegação direta entre páginas ou scroll infinito
Selecione o método de paginação de acordo com o cenário: OFFSET ou Cursor
Garanta existência de índices nos campos usados para ordenação ou cursor
Teste performance de queries reais com Explain ou ferramentas similares
Evite cursors em campos UUID v4; use UUID v7, datas ou incrementais
Implemente e monitore consumo de recursos no banco e app

Domine React e Node com o CrazyStack

Aprenda técnicas avançadas de React com nosso curso completo