Les curseurs sont un choix raisonnable pour la pagination dans les petites applications intranet qui fonctionnent avec de grands ensembles de données, mais vous devez être prêt à les supprimer après un délai d'attente. Les utilisateurs aiment flâner, aller déjeuner, partir en vacances pendant deux semaines, etc., et laisser tourner leurs applications. S'il s'agit d'une application Web, il y a même la question de savoir ce qu'est "en cours d'exécution" et comment savoir si l'utilisateur est toujours là.
Ils ne conviennent pas aux applications à grande échelle avec un nombre élevé de clients et des clients qui vont et viennent presque au hasard, comme dans les applications Web ou les API Web. Je ne recommanderais pas d'utiliser des curseurs dans votre application à moins que vous ayez un nombre de clients assez petit et des taux de requêtes très élevés ... auquel cas l'envoi de petits lots de lignes sera très inefficace et vous devriez penser à autoriser les requêtes de plage, etc. à la place.
Les curseurs ont plusieurs coûts. Si le curseur n'est pas WITH HOLD
vous devez garder une transaction ouverte. La transaction ouverte peut empêcher l'autovacuum de faire son travail correctement, provoquant un gonflement de la table et d'autres problèmes. Si le curseur est déclaré WITH HOLD
et la transaction n'est pas maintenue ouverte, vous devez payer le coût de la matérialisation et du stockage d'un ensemble de résultats potentiellement volumineux - du moins, je pense que c'est ainsi que fonctionnent les curseurs de maintien. L'alternative est tout aussi mauvaise, gardant la transaction implicitement ouverte jusqu'à ce que le curseur soit détruit et empêchant le nettoyage des lignes.
De plus, si vous utilisez des curseurs, vous ne pouvez pas remettre les connexions à un pool de connexions. Vous aurez besoin d'une connexion par client. Cela signifie que davantage de ressources backend sont utilisées uniquement pour maintenir l'état de la session, et définit une limite supérieure très réelle sur le nombre de clients que vous pouvez gérer avec une approche basée sur le curseur.
Il y a aussi la complexité et la surcharge de la gestion d'une configuration basée sur un curseur avec état par rapport à une approche de regroupement de connexions sans état avec limite et décalage. Vous devez faire expirer les curseurs de votre application après un délai d'expiration ou vous faites face à une utilisation potentiellement illimitée des ressources sur le serveur, et vous devez garder une trace de quelles connexions ont quels curseurs pour quels ensembles de résultats pour quels utilisateurs....
En général, malgré le fait qu'il puisse être assez inefficace, LIMIT
et OFFSET
peut être la meilleure solution. Il peut souvent être préférable de rechercher la clé primaire plutôt que d'utiliser OFFSET
, cependant.
Au fait, vous regardiez la documentation des curseurs en PL/pgSQL. Vous voulez des curseurs de niveau SQL normaux pour ce travail.
Les curseurs nécessitent-ils qu'une connexion à la base de données soit laissée ouverte ?
Oui.
Les curseurs s'exécutent-ils à l'intérieur d'une transaction, verrouillant les ressources jusqu'à ce qu'elles soient "fermées" ?
Oui, sauf s'ils sont WITH HOLD
, auquel cas ils consomment d'autres ressources de la base de données.
Y a-t-il d'autres "pièges" dont je ne suis pas au courant ?
Oui, comme ce qui précède devrait l'expliquer.