Dlaczego jest wolny :Jeśli po prostu użyłeś adnotacji przy dwóch polach ManyToMany następnie tworzysz niechciane duże połączenie wszystkich tych tabel razem. Rozmiar iloczynu kartezjańskiego wierszy, które muszą zostać ocenione, wynosi w przybliżeniu Have.objects.count() * Want.objects.count()
. Napisałeś wtedy distinct=True
aby ostatecznie ograniczyć liczbę duplikatów, aby nie uzyskać nieprawidłowego ogromnego wyniku.
Poprawka dla starego Django:Jeśli chcesz używać tylko queryset.annotate(have_count=Count("have"))
szybko uzyskasz właściwy wynik bez distinct=True
lub ten sam wynik również szybko z wyraźnym. Następnie możesz połączyć wyniki dwóch zapytań przez Pythona w pamięci.
Rozwiązanie Dobre rozwiązanie jest możliwe w Django>=1.11 (dwa lata po Twoim pytaniu), używając zapytania z dwa podzapytania , jeden dla Have
i jeden dla Want
, wszystko według jednego żądania, ale nie mieszaj wszystkich tabel.
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))
Zweryfikuj :Możesz sprawdzić zarówno wolne, jak i stałe zapytanie SQL, drukując str(my_queryset.query)
że jest jak opisano powyżej.