2009-07-03 12 views
52

Vorrei chiedere che cosa è la differenza traSQLAlchemy - Differenza tra query e query.all in cicli for

for row in session.Query(Model1): 
    pass 

e

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

è il primo in qualche modo un iteratore bombardando vostro DB con singolo Query e quest'ultimo "ansioso" interroga l'intera cosa come una lista (come intervallo (x) vs xrange (x))?

risposta

73

No, non c'è differenza nel traffico DB. La differenza è che il primo fa funzionare l'ORM su ogni riga quando sta per dartelo, mentre il secondo fa funzionare l'ORM su tutte le righe, prima di iniziare a dartelo.

Si noti che q.all() è solo zucchero per list(q), vale a dire la raccolta di tutto il rendimento dal generatore in una lista. Ecco il source code per esso, nella classe Query (trovare def all in origine collegata):

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) 

... dove self, l'oggetto query, è un iterabile, cioè ha un metodo __iter__.

Quindi logicamente i due modi sono esattamente gli stessi in termini di traffico DB; entrambi finiscono per chiamare query.__iter__() per ottenere un iteratore di riga e next() attraverso di esso.

La differenza pratica è che il precedente può iniziare a fornire le righe non appena i loro dati sono arrivati, "streaming" del risultato del DB impostato, con meno utilizzo della memoria e latenza. Non posso affermare con certezza che tutte le attuali implementazioni del motore lo facciano (spero lo facciano!). In ogni caso quest'ultima versione impedisce tale efficienza, senza una buona ragione.

+0

grazie, questa è una risposta eccellente – Tom

+9

[questo post] (http://www.mail-archive.com/[email protected]/msg12443.html) fa luce sui dettagli di implementazione. Risposta breve: '__iter__' * fa * preleva tutti i risultati (per una buona ragione), ma questo comportamento può essere cambiato se sai cosa stai facendo. – Coquelicot

+0

Quindi non c'è alcun vantaggio nell'usare 'q.all()'? – dshgna

Problemi correlati