Question

J'exécute une requête sur une table dans une base de données postgresql. La base de données est sur un ordinateur distant. La table contient environ 30 sous-tables utilisant postgresql fonctionnalité de partitionnement . .

La requête renvoie un ensemble de résultats volumineux, d'environ 1,8 million de lignes.

Dans mon code, j'utilise le support spring jdbc, méthode JdbcTemplate.query , mais mon RowCallbackHandler n'est pas appelé.

Ma meilleure hypothèse est que le pilote postgresql jdbc (j'utilise la version 8.3-603.jdbc4) accumule le résultat en mémoire avant d'appeler mon code. Je pensais que le La configuration fetchSize peut contrôler cela, mais je l’ai essayé et rien ne change. Je l'ai fait comme manuel postgresql recommandé .

Cette requête a bien fonctionné avec Oracle XE. Mais j'essaie de migrer vers postgresql à cause de la fonctionnalité de partitionnement, qui n'est pas disponible dans Oracle XE.

Mon environnement:

  • Postgresql 8.3
  • Windows Server 2008 Enterprise 64 bits
  • JRE 1.6 64 bits
  • Spring 2.5.6
  • Pilote JDBC Postgresql 8.3-603
Était-ce utile?

La solution

Pour utiliser un curseur pour récupérer des données, vous devez définir le type ResultSet de ResultSet.TYPE_FORWARD_ONLY (valeur par défaut) et autocommit sur false en plus de définir une taille d'extraction. C’est ce qui est mentionné dans la documentation à laquelle vous avez accédé, mais vous n’avez pas mentionné explicitement que vous avez suivi ces étapes.

Faites attention au schéma de partitionnement de PostgreSQL. Cela fait vraiment très mal avec l'optimiseur et peut causer d'énormes problèmes de performances là où il ne devrait pas y en avoir (en fonction des spécificités de vos données). Dans tous les cas, votre ligne ne contient-elle que 1,8 million de lignes? Il n'y a aucune raison pour qu'il soit partitionné en fonction de sa taille, car il est correctement indexé.

Autres conseils

Je parie qu'il n'y a pas un seul client de votre application qui a besoin de 1,8 million de lignes en même temps. Vous devriez penser à un moyen judicieux de réduire les résultats en morceaux plus petits et de donner aux utilisateurs la possibilité de les parcourir.

C'est ce que Google fait. Lorsque vous effectuez une recherche, il peut y avoir des millions de résultats, mais ils renvoient 25 pages à la fois avec l’idée que vous trouverez ce que vous voulez dans la première page.

S'il ne s'agit pas d'un client et que les résultats sont générés d'une manière ou d'une autre, je vous recommande de laisser la base de données traiter toutes ces lignes et renvoyer simplement le résultat. Cela n'a aucun sens de renvoyer 1,8 million de lignes pour effectuer un calcul sur le niveau intermédiaire.

Si aucun de ces cas ne s’applique, vous avez un réel problème. Il est temps de repenser cela.

Après avoir lu les réponses ultérieures, il me semble qu’il s’agit plus d’une solution de génération de rapports qui devrait être traitée par lots ou calculée en temps réel et stockée dans des tables qui ne font pas partie de votre système transactionnel. Il est impossible d’ajouter 1,8 million de lignes au niveau intermédiaire pour le calcul des moyennes mobiles.

Je vous conseillerais de vous réorienter - commencez à y penser comme une solution de reporting.

La propriété fetchSize a fonctionné comme décrit à l'adresse du manuel postgres . .

Mon erreur est que je définissais auto commit = false sur une connexion provenant d'un pool de connexions autre que la connexion utilisée par l'instruction préparée.

Merci pour tous vos commentaires.

J'ai fait tout ce qui précède, mais il me fallait un dernier élément: assurez-vous que l'appel est encapsulé dans une transaction et réglez la transaction sur lecture seule, de sorte qu'aucun état d'annulation ne soit requis.

J'ai ajouté ceci: @Transactional (readOnly = true)

Salut.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top