Este é um problema sem uma solução perfeitamente satisfatória porque você está tentando combinar requisitos essencialmente incompatíveis:
-
Envie apenas a quantidade necessária de dados para o cliente sob demanda, ou seja, você não pode baixar todo o conjunto de dados e paginar no lado do cliente.
-
Minimize a quantidade de estado por cliente que o servidor deve acompanhar, para escalabilidade com um grande número de clientes.
-
Manter estado diferente para cada cliente
Este é um tipo de situação de "escolha dois". Você tem que se comprometer; aceite que você não pode manter o estado de paginação de cada cliente exatamente correto, aceite que você precisa baixar um conjunto de big data para o cliente ou aceite que você precisa usar uma enorme quantidade de recursos do servidor para manter o estado do cliente.
Existem variações dentro daquelas que misturam os vários compromissos, mas é nisso que tudo se resume.
Por exemplo, algumas pessoas enviarão ao cliente algumas dados extras, suficientes para satisfazer a maioria dos requisitos do cliente. Se o cliente exceder isso, a paginação será quebrada.
Alguns sistemas armazenam em cache o estado do cliente por um curto período (com tabelas não registradas de curta duração, arquivos temporários ou qualquer outra coisa), mas expiram rapidamente, portanto, se o cliente não estiver constantemente solicitando dados novos, a paginação será quebrada.
etc.
Veja também:
- Como fornecer a um cliente de API 1.000.000 resultados de banco de dados?
- Usando "Cursores" para paginação no PostgreSQL
- Iterar em banco de dados postgres externo grande, manipular linhas, gravar saída em banco de dados postgres de trilhos
- otimização de desempenho de compensação/limite
- Se a contagem do PostgreSQL(*) for sempre lenta, como paginar consultas complexas?
- Como retornar uma linha de amostra do banco de dados uma a uma
Eu provavelmente implementaria uma solução híbrida de alguma forma, como:
-
Usando um cursor, leia e envie imediatamente a primeira parte dos dados para o cliente.
-
Busque imediatamente dados extras suficientes do cursor para satisfazer 99% dos requisitos dos clientes. Armazene-o em um cache rápido e inseguro como memcached, Redis, BigMemory, EHCache, qualquer que seja sob uma chave que me permita recuperá-lo para solicitações posteriores do mesmo cliente. Em seguida, feche o cursor para liberar os recursos do banco de dados.
-
Expirar o cache em uma base de uso menos recente, portanto, se o cliente não continuar lendo rápido o suficiente, ele precisará obter um novo conjunto de dados do banco de dados e a paginação será alterada.
-
Se o cliente quiser mais resultados do que a grande maioria de seus pares, a paginação mudará em algum momento à medida que você alternar para a leitura direta do banco de dados em vez do cache ou gerar um novo conjunto de dados em cache maior.
Dessa forma, a maioria dos clientes não notará problemas de paginação e você não precisará enviar grandes quantidades de dados para a maioria dos clientes, mas não derreterá seu servidor de banco de dados. No entanto, você precisa de um grande cache para se safar disso. Sua prática depende se seus clientes podem lidar com a quebra de paginação - se simplesmente não for aceitável quebrar a paginação, você ficará preso ao lado do banco de dados com cursores, tabelas temporárias, copiando todo o conjunto de resultados na primeira solicitação, etc. Também depende do tamanho do conjunto de dados e da quantidade de dados que cada cliente geralmente requer.