La plupart des implémentations DBAPI mettent entièrement les lignes en mémoire tampon au fur et à mesure qu'elles sont extraites - donc généralement, avant que l'ORM SQLAlchemy n'obtienne même un résultat, l'ensemble de résultats est en mémoire.
Mais alors, la façon dont Query
fonctionne est qu'il charge complètement le jeu de résultats donné par défaut avant de vous rendre vos objets. La justification ici concerne les requêtes qui sont plus que de simples instructions SELECT. Par exemple, dans les jointures à d'autres tables qui peuvent renvoyer la même identité d'objet plusieurs fois dans un jeu de résultats (commun avec un chargement hâtif), l'ensemble complet de lignes doit être en mémoire afin que les résultats corrects puissent être renvoyés sinon des collections et autres pourrait n'être que partiellement peuplé.
Query
Offre donc une option pour modifier ce comportement yield_per()
. Cet appel amènera le Query
à produire des lignes par lots, où vous lui donnez la taille du lot. Comme l'état de la documentation, cela n'est approprié que si vous n'effectuez aucun chargement impatient de collections, c'est donc essentiellement si vous savez vraiment ce que vous faites. De plus, si le DBAPI sous-jacent pré-tamponne les lignes, il y aura toujours cette surcharge de mémoire, donc l'approche ne s'adapte que légèrement mieux que de ne pas l'utiliser.
Je n'utilise presque jamais yield_per()
; à la place, j'utilise une meilleure version de l'approche LIMIT que vous suggérez ci-dessus en utilisant les fonctions de fenêtre. LIMIT et OFFSET ont un énorme problème: de très grandes valeurs OFFSET font que la requête devient de plus en plus lente, car un OFFSET de N la fait parcourir N lignes - c'est comme faire la même requête cinquante fois au lieu d'une, chaque fois en lisant un nombre de rangées de plus en plus grand. Avec une approche de fonction de fenêtre, je pré-extrait un ensemble de valeurs de «fenêtre» qui se réfèrent à des morceaux de la table que je veux sélectionner. J'émets ensuite des instructions SELECT individuelles que chacune tire de l'une de ces fenêtres à la fois.
L'approche de la fonction de fenêtre est sur le wiki et je l'utilise avec beaucoup de succès.
Notez également: toutes les bases de données ne prennent pas en charge les fonctions de fenêtre; vous avez besoin de Postgresql, Oracle ou SQL Server. IMHO utiliser au moins Postgresql en vaut vraiment la peine - si vous utilisez une base de données relationnelle, vous pouvez aussi bien utiliser le meilleur.