PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Perché questo conteggio delle annotazioni di Django (1.6) è così lento?

Perché è lento :se hai semplicemente utilizzato l'annotazione di due campi ManyToMany quindi crei un big join indesiderato di tutte queste tabelle insieme. La dimensione del prodotto cartesiano delle righe che deve essere valutata è approssimativamente Have.objects.count() * Want.objects.count() . Hai scritto quindi distinct=True per limitare infine il numero di elementi duplicati per non ottenere un risultato enorme non valido.

Risolto il problema con il vecchio Django:se dovessi utilizzare solo queryset.annotate(have_count=Count("have")) otterrai rapidamente il risultato giusto senza distinct=True o lo stesso risultato anche veloce con distinto. Quindi puoi combinare i risultati di due query di Python in memoria.

Soluzione Una buona soluzione è possibile in Django>=1.11 (due anni dopo la tua domanda) utilizzando una query con due sottoquery , uno per Have e uno per Want , tutto per una richiesta, ma non per mescolare tutte le tabelle insieme.

from django.db.models import Count, OuterRef, Subquery

sq = Collection.objects.filter(pk=OuterRef('pk')).order_by()
have_count_subq = sq.values('have').annotate(have_count=Count('have')).values('have_count')
want_count_subq = sq.values('want').annotate(have_count=Count('want')).values('want_count')
queryset = queryset.annotate(have_count=Subquery(have_count_subq),
                             want_count=Subquery(want_count_subq))

Verifica :Puoi controllare sia la query SQL lenta che quella fissa stampando str(my_queryset.query) che è come descritto sopra.