PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Utilizzo dei cursori per il paging in PostgreSQL

I cursori sono una scelta ragionevole per il paging in applicazioni intranet più piccole che funzionano con set di dati di grandi dimensioni, ma è necessario essere preparati a eliminarli dopo un timeout. Agli utenti piace allontanarsi, andare a pranzo, andare in vacanza per due settimane, ecc. e lasciare le applicazioni in esecuzione. Se si tratta di un'app basata sul Web, c'è persino la domanda su cosa sia "in esecuzione" e come sapere se l'utente è ancora in giro.

Non sono adatti per applicazioni su larga scala con un numero elevato di client e client che vanno e vengono in modo quasi casuale come nelle app basate sul Web o nelle API Web. Non consiglierei di utilizzare i cursori nella tua applicazione a meno che tu non abbia un numero di clienti abbastanza piccolo e tassi di richiesta molto elevati ... nel qual caso l'invio di piccoli batch di righe sarà molto inefficiente e dovresti invece pensare di consentire richieste di intervallo ecc.

I cursori hanno diversi costi. Se il cursore non è WITH HOLD devi mantenere una transazione aperta. La transazione aperta può impedire all'autovacuum di svolgere correttamente il proprio lavoro, causando rigonfiamenti della tabella e altri problemi. Se il cursore è dichiarato WITH HOLD e la transazione non viene tenuta aperta, devi pagare il costo di materializzazione e archiviazione di un set di risultati potenzialmente grande - almeno, penso che sia così che funzionano i cursori di attesa. L'alternativa è altrettanto pessima, mantenendo implicitamente aperta la transazione fino a quando il cursore non viene distrutto e impedendo la pulizia delle righe.

Inoltre, se utilizzi i cursori, non puoi restituire le connessioni a un pool di connessioni. Avrai bisogno di una connessione per client. Ciò significa che vengono utilizzate più risorse di back-end solo mantenendo lo stato della sessione e imposta un limite superiore molto reale al numero di client che puoi gestire con un approccio basato sul cursore.

C'è anche la complessità e il sovraccarico della gestione di una configurazione stateful, basata sul cursore rispetto a un approccio di pool di connessioni stateless con limite e offset. Devi fare in modo che la tua applicazione scada i cursori dopo un timeout o devi affrontare un uso potenzialmente illimitato delle risorse sul server e devi tenere traccia di quali connessioni hanno quali cursori per quali set di risultati per quali utenti....

In generale, nonostante possa essere abbastanza inefficiente, LIMIT e OFFSET può essere la soluzione migliore. Spesso può essere meglio cercare la chiave primaria piuttosto che usare OFFSET , però.

A proposito, stavi guardando la documentazione per i cursori in PL/pgSQL. Vuoi normali cursori a livello SQL per questo lavoro.

I cursori richiedono che una connessione al database sia lasciata aperta?

Sì.

I cursori vengono eseguiti all'interno di una transazione, bloccando le risorse finché non vengono "chiuse"?

Sì, a meno che non siano WITH HOLD , nel qual caso consumano altre risorse del database.

Ci sono altri "trucchi" di cui non sono a conoscenza?

Sì, come dovrebbe spiegare quanto sopra.