Il s'agit d'un problème sans solution parfaitement satisfaisante car vous essayez de combiner des exigences essentiellement incompatibles :
-
Envoyez uniquement la quantité de données requise au client à la demande, c'est-à-dire que vous ne pouvez pas télécharger l'ensemble de données puis le paginer côté client.
-
Minimisez la quantité d'états par client dont le serveur doit assurer le suivi, pour une évolutivité avec un grand nombre de clients.
-
Maintenir un état différent pour chaque client
Il s'agit d'une situation de type "choisissez-en deux". Vous devez faire des compromis; acceptez que vous ne puissiez pas conserver exactement l'état de pagination de chaque client, acceptez que vous deviez télécharger un ensemble de données volumineuses sur le client ou acceptez que vous deviez utiliser une énorme quantité de ressources serveur pour maintenir l'état du client.
Il existe des variations au sein de ceux qui mélangent les différents compromis, mais c'est à cela que tout se résume.
Par exemple, certaines personnes enverront au client quelques données supplémentaires, suffisantes pour satisfaire la plupart des besoins des clients. Si le client dépasse cela, il obtient une pagination cassée.
Certains systèmes mettront en cache l'état du client pendant une courte période (avec des tables non enregistrées de courte durée, des fichiers temporaires, etc.), mais l'expireront rapidement, donc si le client ne demande pas constamment de nouvelles données, sa pagination est cassée.
Etc.
Voir aussi :
- Comment fournir à un client API 1 000 000 résultats de base de données ?
- Utilisation des "curseurs" pour la pagination dans PostgreSQL
- Itérer sur une grande base de données postgres externe, manipuler des lignes, écrire la sortie dans des rails postgres db
- optimisation des performances de décalage/limite
- Si PostgreSQL count(*) est toujours lent, comment paginer les requêtes complexes ?
- Comment renvoyer un exemple de ligne de la base de données une par une
J'implémenterais probablement une solution hybride d'une certaine forme, comme :
-
À l'aide d'un curseur, lisez et envoyez immédiatement la première partie des données au client.
-
Récupérez immédiatement suffisamment de données supplémentaires à partir du curseur pour satisfaire 99 % des besoins des clients. Stockez-le dans un cache rapide et non sécurisé comme memcached, Redis, BigMemory, EHCache, quoi que ce soit sous une clé qui me permettra de le récupérer pour des demandes ultérieures par le même client. Fermez ensuite le curseur pour libérer les ressources de la base de données.
-
Faites expirer le cache sur la base de l'utilisation la moins récente, donc si le client ne continue pas à lire assez rapidement, il doit aller chercher un nouvel ensemble de données à partir de la base de données, et la pagination change.
-
Si le client veut plus de résultats que la grande majorité de ses pairs, la pagination changera à un moment donné lorsque vous passerez à la lecture directe à partir de la base de données plutôt que du cache ou générerez un nouvel ensemble de données en cache plus grand.
De cette façon, la plupart des clients ne remarqueront pas les problèmes de pagination et vous n'aurez pas à envoyer de grandes quantités de données à la plupart des clients, mais vous ne ferez pas fondre votre serveur de base de données. Cependant, vous avez besoin d'un gros cache boofy pour vous en sortir. Sa pratique dépend de la capacité de vos clients à faire face à la rupture de pagination - s'il n'est tout simplement pas acceptable de casser la pagination, alors vous êtes obligé de le faire côté DB avec des curseurs, des tables temporaires, en faisant face à l'ensemble des résultats à la première demande, etc. Cela dépend également de la taille de l'ensemble de données et de la quantité de données dont chaque client a généralement besoin.