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.