web-dev-qa-db-fra.com

Sqlalchemy - Différence entre query et query.all dans les boucles

Je voudrais demander quelle est la différence entre

for row in session.Query(Model1):
    pass

et

for row in session.Query(Model1).all():
    pass

le premier est-il en quelque sorte un itérateur qui bombarde votre base de données avec des requêtes uniques et le dernier "désireux" interroge le tout sous forme de liste (comme range (x) vs xrange (x))?

67
Tom

Non, il n'y a aucune différence dans le trafic DB. La différence est juste que for row in session.Query(Model1) fait l'ORM travailler sur chaque ligne quand il est sur le point de vous le donner, tandis que for row in session.Query(Model1).all() fait l'ORM travailler sur toutes les lignes, avant de commencer à leur donner à toi.

Notez que q.all() n'est que du sucre pour list(q), c'est-à-dire rassemblant tout ce qui est produit par le générateur dans une liste. Voici le code source pour cela, dans la classe Query (trouvez def all Dans la source liée):

def all(self):
    """Return the results represented by this ``Query`` as a list.

    This results in an execution of the underlying query.

    """
    return list(self)

... où self, l'objet de requête, est un itérable, c'est-à-dire a une méthode __iter__.

Donc, logiquement, les deux façons sont exactement les mêmes en termes de trafic DB; les deux finissent par appeler query.__iter__() pour obtenir un itérateur de ligne, et next() en chemin.

La différence pratique est que les premiers peuvent commencer à vous donner des lignes dès que leurs données sont arrivées, "diffusant" le jeu de résultats DB avec moins utilisation de la mémoire et latence. Je ne peux pas affirmer avec certitude que toutes les implémentations actuelles du moteur le font (j'espère qu'elles le font!). En tout cas, cette dernière version empêche cette efficacité, sans raison valable.

94
Gunnlaugur Briem