PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Verwenden von Cursorn zum Paging in PostgreSQL

Cursor sind eine vernünftige Wahl für das Paging in kleineren Intranetanwendungen, die mit großen Datensätzen arbeiten, aber Sie müssen darauf vorbereitet sein, sie nach einer Zeitüberschreitung zu verwerfen. Benutzer gehen gerne weg, gehen zum Mittagessen, fahren zwei Wochen in den Urlaub usw. und lassen ihre Anwendungen laufen. Wenn es sich um eine webbasierte App handelt, stellt sich sogar die Frage, was "Running" ist und wie man erkennt, ob der Benutzer noch da ist.

Sie eignen sich nicht für groß angelegte Anwendungen mit vielen Clients und Clients, die nahezu zufällig kommen und gehen, wie in webbasierten Apps oder Web-APIs. Ich würde die Verwendung von Cursorn in Ihrer Anwendung nicht empfehlen, es sei denn, Sie haben eine relativ kleine Anzahl von Clients und sehr hohe Anforderungsraten ... in diesem Fall ist das Senden winziger Reihen von Zeilen sehr ineffizient und Sie sollten stattdessen darüber nachdenken, Bereichsanforderungen usw. zuzulassen.

Cursor haben mehrere Kosten. Wenn der Cursor nicht WITH HOLD ist Sie müssen eine Transaktion offen halten. Die offene Transaktion kann verhindern, dass Autovacuum seine Arbeit ordnungsgemäß verrichtet, was zu Tabellenaufblähungen und anderen Problemen führt. Wenn der Cursor als WITH HOLD deklariert ist und die Transaktion nicht offen gehalten wird, müssen Sie die Kosten für die Materialisierung und Speicherung einer potenziell großen Ergebnismenge bezahlen - zumindest denke ich, dass so Hold-Cursor funktionieren. Die Alternative ist genauso schlecht, sie hält die Transaktion implizit offen, bis der Cursor zerstört wird, und verhindert, dass Zeilen bereinigt werden.

Wenn Sie außerdem Cursor verwenden, können Sie Verbindungen nicht an einen Verbindungspool zurückgeben. Sie benötigen eine Verbindung pro Client. Das bedeutet, dass mehr Backend-Ressourcen verwendet werden, nur um den Sitzungsstatus aufrechtzuerhalten, und setzt eine sehr reale Obergrenze für die Anzahl der Clients, die Sie mit einem Cursor-basierten Ansatz handhaben können.

Hinzu kommen die Komplexität und der Overhead der Verwaltung eines zustandsbehafteten, Cursor-basierten Setups im Vergleich zu einem zustandslosen Connection-Pooling-Ansatz mit Limit und Offset. Sie müssen Ihre Anwendungs-Cursor nach einer Zeitüberschreitung ablaufen lassen, oder Sie sehen sich einer potenziell unbegrenzten Ressourcennutzung auf dem Server gegenüber, und Sie müssen verfolgen, welche Verbindungen welche Cursor für welche Ergebnismengen für welche Benutzer haben ....

Im Allgemeinen, trotz der Tatsache, dass es ziemlich ineffizient sein kann, LIMIT und OFFSET kann die bessere Lösung sein. Es kann oft besser sein, den Primärschlüssel zu suchen, anstatt OFFSET zu verwenden , obwohl.

Übrigens haben Sie sich die Dokumentation für Cursor in PL/pgSQL angesehen. Sie möchten für diesen Job normale Cursor auf SQL-Ebene.

Erfordern die Cursor, dass eine Datenbankverbindung offen gelassen wird?

Ja.

Laufen die Cursor innerhalb einer Transaktion und sperren Ressourcen, bis sie "geschlossen" werden?

Ja, es sei denn, sie sind WITH HOLD , in diesem Fall verbrauchen sie andere Datenbankressourcen.

Gibt es noch andere "Fallstricke", die mir nicht bekannt sind?

Ja, wie oben erklärt werden sollte.