Quelles sont les meilleures pratiques pour la mise en cache des résultats paginés dont l'ordre / les propriétés peuvent changer?

11

Quelle est la meilleure pratique pour mettre en cache les résultats de recherche paginés dont l'ordre / les propriétés peuvent être modifiés?

Disons que dans ma candidature, quelqu'un veut voir les 20 derniers fils de discussion (sur 10 000). Une demande serait envoyée à la base de données, via servlet, pour récupérer les 20 premiers enregistrements de la table des fils de discussion au format XML / JSON. S'ils veulent ensuite voir les 20 prochains, ils passent à la page de résultats suivante et cela déclenche une autre demande pour obtenir le lot suivant (limite et décalage = 20, etc.).

Afin de réduire la charge du serveur et l'attente du client, je voudrais mettre en cache les pages de résultats précédentes. Cependant, j'ai deux questions:

  1. Le tableau dans lequel les résultats sont affichés peut être ordonné par plus d'un attribut (c'est-à-dire, date de création du fil, auteur du fil, dernière date de post). Cela signifie qu'une déclaration comme «les 20 premiers résultats» n'a aucun sens sans contexte (c'est-à-dire, par quoi ordonnons-nous). Comment le serveur frontal communique-t-il alors au serveur principal ce qu'il a déjà chargé? Ma première pensée a été d'utiliser des identifiants pour chaque résultat, mais les renvoyer au serveur lors de requêtes ultérieures (et filtrer les résultats en fonction d'eux) prendrait autant de temps que de tout renvoyer à l'aveuglette. Comment puis-je faire ceci?
  2. Que se passe-t-il si un attribut d'un résultat précédemment renvoyé (c'est-à-dire le plus récent post-date) a changé? Nous avons ensuite besoin d'un moyen de vérifier chaque résultat pour voir s'il a été modifié côté serveur depuis qu'il a été paginé. Comment faire?
bazar
la source
Votre exemple est un peu rude. S'il ne s'agit que de 100 threads, vous feriez mieux de télécharger les 100 en une seule fois. Si vous en tirez 20 sur 10 000, c'est une autre histoire.
Dan Pichelman
@DanPichelman Désolé, j'étais un peu flou. Ce serait plus comme 10 000.
goodsquishy
Numéro modifié pour plus de clarté.
goodsquishy
Est-ce http? Si c'est le cas, pourquoi ne pas simplement mettre le cache en fonction de l'URL? Avoir tous les paramètres dans l'url. S'il s'agit d'un navigateur, essayez d'utiliser le cache du navigateur. S'il s'agit d'une application, définissez une expiration de cache. Volley d'Android fonctionne assez bien.
frostymarvelous

Réponses:

7

Il semble que vous avez besoin est un wrapper pour tous les paramètres qui définissent une page ( par exemple, pageNumber, pageSize, sortType, totalCount, etc.) et d' utiliser cet DataRequestobjet comme la clé de votre mécanisme de mise en cache. À partir de là, vous disposez d'un certain nombre d'options pour gérer le cache:

  • Implémentez une sorte de mécanisme de temporisation pour actualiser le cache (en fonction de la fréquence à laquelle les données changent).
  • Avoir un écouteur qui vérifie les modifications de la base de données et met à jour le cache en fonction des paramètres ci-dessus.
  • Si les modifications sont effectuées par le même processus, vous pouvez toujours marquer le cache comme obsolète à chaque modification et vérifier cet indicateur lorsqu'une page est demandée.

Les deux premiers peuvent impliquer un mécanisme de planification pour se déclencher sur un certain intervalle ou basé sur un événement. Le dernier pourrait être le plus simple si vous avez un seul point d'accès aux données.

Enfin, comme @DanPichelman l'a mentionné, il peut rapidement devenir un algorithme trop compliqué qui l'emporte sur les avantages, alors assurez-vous que le gain de performances justifie la complexité de l'algorithme.

rae1
la source
3

Je le manipulerais probablement comme ceci:

  1. Traitez les différents ordres comme des séquences différentes toutes ensemble. Il ne vaudra pas la tenue de livres supplémentaires pour suivre ce que chaque client a (ou le renvoyer encore et encore).
  2. Chaque fois que les pages utilisateur s'affichent immédiatement à partir du cache tout en envoyant en même temps un GET au serveur qui comprend soit un hachage soit un dernier accès. Le serveur ne renvoie une page complète que si quelque chose a changé.
  3. Récupérez du serveur plus d'une page d'interface utilisateur à la fois. Par exemple, si votre interface utilisateur affiche 20 entrées, interrogez 60. Je dois tester celle-ci, mais je m'attends à ce que la taille de retour la plus efficace soit généralement supérieure à la quantité moyenne de données affichées sur une page. Cela rend également l'interface utilisateur très réactive pour certains tours de page.
  4. La prélecture se réenclenche lorsque vous approchez d'une limite. Cela permet de préserver ces temps de chargement rapides à partir du cache.
Chris Pitman
la source
2

Juste une pensée - dans votre appel serveur, transmettez les paramètres habituels ainsi qu'un tableau de hachages MD5 représentant les pages de données vues précédemment mises en cache.

L'appel de retour contiendrait toutes les données habituelles pour la nouvelle page actuelle, ainsi que des mises à jour pour toutes les pages obsolètes précédemment consultées. Vous pouvez utiliser l'ancien hachage comme clé.

Je recommanderais d'abord de nombreux tests de performances et de synchronisation - votre code côté client sera beaucoup plus compliqué qu'il ne le serait si vous frappiez simplement le serveur pour chaque page de données. Assurez-vous que la complexité supplémentaire entraîne une amélioration significative.

Dan Pichelman
la source
Merci pour votre réponse. Je pensais au hachage, mais je ne sais pas si cela aidera le scénario de réorganisation (c'est-à-dire qu'il n'est pas assez granulaire et ne fonctionne que par page, pas par résultat). Je pense que votre dernier paragraphe est un bon point, et je commence à penser que la complexité de toute solution possible l'emporterait sur les avantages en termes de performances.
goodsquishy