Защо е бавен :Ако просто сте използвали анотацията от две полета ManyToMany след това създавате нежелано голямо съединение на всички тези таблици заедно. Размерът на декартовото произведение на редовете, които трябва да бъдат оценени, е приблизително Have.objects.count() * Want.objects.count()
. Тогава сте написали distinct=True
за да ограничите най-накрая броя на дублираните елементи, за да не получите невалиден огромен резултат.
Поправка за старо Django:Ако бихте използвали само queryset.annotate(have_count=Count("have"))
ще получите правилния резултат бързо без distinct=True
или същият резултат също бързо с различни. След това можете да комбинирате резултати от две заявки от Python в паметта.
Решение В Django>=1.11 е възможно добро решение (две години след вашия въпрос) чрез използване на заявка с две подзаявки , един за Have
и един за Want
, всички с една заявка, но не и да смесвате всички таблици заедно.
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))
Потвърдете :Можете да проверите както бавната, така и фиксираната SQL заявка, като отпечатате str(my_queryset.query)
че е както е описано по-горе.