Die Tabelle hat einen Primärschlüssel. Nutzen Sie es.
Statt LIMIT
und OFFSET
, führen Sie Ihre Paging mit einem Filter für den Primärschlüssel durch. Sie haben dies mit Ihrem Kommentar angedeutet:
Paging mit Zufallszahlen (Fügen Sie "GREATER THAN ORDER BY" zu jeder Abfrage hinzu)
aber es gibt nichts Zufälliges darüber, wie Sie es tun sollten.
SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2
Erlauben Sie dem Client, beide Parameter anzugeben, die letzte ID, die er gesehen hat, und die Anzahl der abzurufenden Datensätze. Ihre API muss entweder einen Platzhalter, einen zusätzlichen Parameter oder einen alternativen Aufruf für "fetch the first" enthalten n IDs", wobei WHERE
weggelassen wird -Klausel aus der Abfrage, aber das ist trivial.
Dieser Ansatz verwendet einen ziemlich effizienten Index-Scan, um die Datensätze in Ordnung zu bringen, und vermeidet im Allgemeinen eine Sortierung oder die Notwendigkeit, alle übersprungenen Datensätze zu durchlaufen. Der Client kann entscheiden, wie viele Zeilen er gleichzeitig haben möchte.
Dieser Ansatz unterscheidet sich vom LIMIT
und OFFSET
Ansatz auf eine zentrale Art und Weise:gleichzeitige Modifikation. Wenn Sie INSERT
in die Tabelle mit einer Taste tiefer als ein Schlüssel, den ein Kunde bereits gesehen hat, wird dieser Ansatz seine Ergebnisse überhaupt nicht ändern, während der OFFSET
Annäherung wird eine Reihe wiederholen. Ebenso, wenn Sie DELETE
eine Zeile mit einer niedrigeren als bereits gesehenen ID ändern sich die Ergebnisse dieses Ansatzes nicht, während OFFSET
überspringt eine unsichtbare Zeile. Es gibt jedoch keinen Unterschied für nur anhängende Tabellen mit generierten Schlüsseln.
Wenn Sie im Voraus wissen, dass der Client die gesamte Ergebnismenge haben möchte, ist es am effizientesten, ihm einfach die gesamte Ergebnismenge ohne dieses Paging-Geschäft zu senden. Da würde ich würde Verwenden Sie einen Cursor. Lesen Sie die Zeilen aus der DB und senden Sie sie so schnell an den Client, wie der Client sie akzeptiert. Diese API müsste Grenzen setzen, wie langsam der Client sein darf, um eine übermäßige Backend-Last zu vermeiden; für einen langsamen Client würde ich wahrscheinlich auf Paging umschalten (wie oben beschrieben) oder das gesamte Cursor-Ergebnis in eine temporäre Datei spoolen und die DB-Verbindung schließen.
Wichtige Vorbehalte :
- Erfordert einen
UNIQUE
Einschränkung /UNIQUE
Index oderPRIMARY KEY
zuverlässig sein - Unterschiedliches gleichzeitiges Änderungsverhalten zu Limit/Offset, siehe oben