Mysql
 sql >> Base de données >  >> RDS >> Mysql

itérateur/générateur SqlAlchemy intégré économe en mémoire ?

La plupart des implémentations DBAPI tamponnent entièrement les lignes au fur et à mesure qu'elles sont récupérées - donc généralement, avant même que l'ORM SQLAlchemy n'obtienne un seul résultat, l'ensemble des 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 renvoyer 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 ensemble de résultats (commun avec le chargement hâtif), l'ensemble complet de lignes doit être en mémoire afin que les résultats corrects puissent être renvoyés sinon collections et autres peut n'être que partiellement rempli.

Donc Query offre une option pour modifier ce comportement via yield_per() . Cet appel provoquera la Query pour produire des lignes par lots, où vous lui donnez la taille du lot. Comme l'indiquent les documents, cela n'est approprié que si vous ne faites aucun type de chargement hâtif de collections, donc c'est essentiellement si vous savez vraiment ce que vous faites. De plus, si la DBAPI sous-jacente pré-tamponne les lignes, il y aura toujours cette surcharge de mémoire, de sorte que 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 en ce que les très grandes valeurs OFFSET ralentissent de plus en plus la requête, 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 lignes de plus en plus grand. Avec une approche de fonction de fenêtre, je pré-récupère un ensemble de valeurs de "fenêtre" qui font référence à des morceaux de la table que je veux sélectionner. J'émets ensuite des instructions SELECT individuelles extraites chacune d'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.

Remarque é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. À mon humble avis, utiliser au moins Postgresql en vaut vraiment la peine - si vous utilisez une base de données relationnelle, autant utiliser le meilleur.