Was sind Best Practices für das Zwischenspeichern von paginierten Ergebnissen, deren Reihenfolge / Eigenschaften sich ändern können?

11

Was ist die beste Vorgehensweise zum Zwischenspeichern von paginierten Suchergebnissen, deren Reihenfolge / Eigenschaften geändert werden können?

Angenommen, in meiner Bewerbung möchte jemand die letzten 20 Diskussionsthreads sehen (von 10.000). Eine Anforderung würde an die Datenbank gesendet servlet, um die ersten 20 Datensätze als XML / JSON aus der Diskussionsthread-Tabelle abzurufen. Wenn sie dann die nächsten 20 sehen möchten, gehen sie zur nächsten Ergebnisseite und dies löst eine weitere Anfrage aus, um das nächste Los zu erhalten (Limit und Offset = 20 usw.).

Um die Serverlast und das Warten auf den Client zu reduzieren, möchte ich die vorherigen Ergebnisseiten zwischenspeichern. Ich habe jedoch zwei Fragen:

  1. Die Tabelle, in der die Ergebnisse angezeigt werden, kann nach mehr als einem Attribut sortiert werden (z. B. Erstellungsdatum des Threads, Autor des Threads, Datum des letzten Beitrags). Dies bedeutet, dass eine Aussage wie 'erste 20 Ergebnisse' ohne Kontext keinen Sinn ergibt (dh nach was bestellen wir). Wie kommuniziert das Front-End dann mit dem Back-End, was es bereits geladen hat? Mein erster Gedanke war, IDs für jedes Ergebnis zu verwenden, aber das Zurücksenden dieser IDs an den Server bei nachfolgenden Anforderungen (und das Filtern der darauf basierenden Ergebnisse) wäre genauso zeitaufwändig wie das blinde Zurücksenden aller Daten. Wie kann ich das machen?
  2. Was ist, wenn sich ein Attribut eines zuvor zurückgegebenen Ergebnisses (dh des letzten Nachdatums) geändert hat? Wir müssen dann jedes Ergebnis überprüfen, um festzustellen, ob es seit der Auslagerung serverseitig geändert wurde. Wie kann ich das tun?
Warenquishy
quelle
Ihr Beispiel ist etwas rau. Wenn es nur 100 Threads sind, sollten Sie am besten alle 100 auf einmal herunterladen. Wenn Sie 20 von 10.000 ziehen, ist das eine andere Geschichte.
Dan Pichelman
@ DanPichelman Sorry, ich war ein wenig unklar. Es wäre eher 10.000.
Warenquishy
Bearbeitete Nummer aus Gründen der Übersichtlichkeit.
Warenquishy
Ist das http? Wenn ja, warum nicht einfach anhand der URL zwischenspeichern? Haben Sie alle Parameter in der URL. Wenn es sich um einen Browser handelt, versuchen Sie, den Browser-Cache zu verwenden. Wenn es sich um eine App handelt, legen Sie einen Cache-Ablauf fest. Android Volley funktioniert ganz gut.
frostymarvelous

Antworten:

7

Es scheint , was Sie brauchen , um ein Wrapper für alle Parameter, die eine Seite definieren (sagen sie pageNumber, pageSize, sortType, totalCount, etc.) und verwenden dieses DataRequestObjekt als Schlüssel für Ihren Caching - Mechanismus. Ab diesem Punkt haben Sie eine Reihe von Optionen, um den Cache zu verwalten:

  • Implementieren Sie einen Timeout-Mechanismus, um den Cache zu aktualisieren (basierend darauf, wie oft sich die Daten ändern).
  • Lassen Sie einen Listener die Datenbankänderungen überprüfen und den Cache anhand der oben genannten Parameter aktualisieren.
  • Wenn die Änderungen im selben Prozess vorgenommen werden, können Sie den Cache bei jeder Änderung als veraltet markieren und dieses Flag aktivieren, wenn eine Seite angefordert wird.

Die ersten beiden können einen Scheduler-Mechanismus beinhalten, der in einem bestimmten Intervall oder basierend auf einem Ereignis ausgelöst wird. Der letzte ist möglicherweise einfacher, wenn Sie einen einzelnen Datenzugriffspunkt haben.

Schließlich kann es, wie @DanPichelman erwähnte, schnell zu einem übermäßig komplizierten Algorithmus werden, der die Vorteile überwiegt. Stellen Sie daher sicher, dass der Leistungsgewinn die Komplexität des Algorithmus rechtfertigt.

rae1
quelle
3

Ich würde wahrscheinlich so damit umgehen:

  1. Behandle verschiedene Ordnungen als verschiedene Sequenzen zusammen. Die zusätzliche Buchhaltung lohnt sich nicht, um zu verfolgen, was jeder Kunde hat (oder um es immer wieder zurückzusenden).
  2. Wenn die Benutzerseiten angezeigt werden, werden sie sofort aus dem Cache angezeigt, während gleichzeitig ein GET an den Server gesendet wird, der entweder einen Hash oder eine letzte Zugriffszeit enthält. Der Server sendet nur dann eine ganze Seite zurück, wenn sich etwas geändert hat.
  3. Rufen Sie mehr als eine UI-Seite gleichzeitig vom Server ab. Wenn Ihre Benutzeroberfläche beispielsweise 20 Einträge anzeigt, fragen Sie 60 ab. Ich muss diesen testen, aber ich gehe davon aus, dass die effizienteste Rückgabegröße normalerweise größer ist als die durchschnittliche Datenmenge, die auf einer Seite angezeigt wird. Dies macht die Benutzeroberfläche auch für einige Seitenumbrüche sehr reaktionsschnell.
  4. Prefetch-Reslts, wenn Sie sich einer Grenze nähern. Dies hilft, diese schnellen Ladezeiten aus dem Cache zu erhalten.
Chris Pitman
quelle
2

Nur ein Gedanke - übergeben Sie in Ihrem Serveraufruf die üblichen Parameter sowie ein Array von MD5-Hashes, die aktuell zwischengespeicherte zuvor angezeigte Datenseiten darstellen.

Der Rückruf würde alle üblichen Daten für die neue aktuelle Seite sowie Aktualisierungen für veraltete zuvor angezeigte Seiten enthalten. Sie können den alten Hash als Schlüssel verwenden.

Ich würde zuerst viele Leistungs- und Timing-Tests empfehlen - Ihr clientseitiger Code wird viel komplizierter sein, als wenn Sie einfach für jede Datenseite auf den Server klicken würden. Stellen Sie sicher, dass die zusätzliche Komplexität zu einer bedeutenden Verbesserung führt.

Dan Pichelman
quelle
Danke für deine Antwort. Ich habe über Hashing nachgedacht, bin mir aber nicht sicher, ob es beim Neuordnungsszenario helfen wird (dh es ist nicht detailliert genug und wird nur pro Seite und nicht pro Ergebnis ausgeführt). Ich denke, Ihr letzter Absatz ist ein guter Punkt, und ich fange an zu glauben, dass die Komplexität einer möglichen Lösung die Leistungsvorteile überwiegen würde.
Warenquishy