sql >> Database >  >> RDS >> PostgreSQL

Waarom is deze Django (1.6) annotatietelling zo traag?

Waarom het traag is :Als u gewoon de annotatie door twee ManyToMany-velden dan maak je een ongewenste grote samenvoeging van al deze tabellen samen. De grootte van het Cartesiaanse product van rijen die moeten worden geëvalueerd, is ongeveer Have.objects.count() * Want.objects.count() . Je schreef toen distinct=True om uiteindelijk het aantal gedupliceerde items te beperken om geen ongeldig groot resultaat te krijgen.

Oplossing voor oude Django:als u alleen queryset.annotate(have_count=Count("have")) zou gebruiken je krijgt snel het juiste resultaat zonder distinct=True of hetzelfde resultaat ook snel met onderscheiden. Dan kunt u de resultaten van twee query's door Python in het geheugen combineren.

Oplossing Een mooie oplossing is mogelijk in Django>=1.11 (twee jaar na uw vraag) door een zoekopdracht met . te gebruiken twee subquery's , één voor Have en één voor Want , allemaal op één verzoek, maar niet om alle tabellen samen te voegen.

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))

Verifiëren :U kunt zowel de langzame als de vaste SQL-query controleren door str(my_queryset.query) af te drukken dat het is zoals hierboven beschreven.




  1. MySQL-GROEP OP NULL en LEEG

  2. MySQL BESTELLEN OP IN()

  3. Hoe de tabelstructuur in Oracle wijzigen?

  4. sqljocky database synchroon opvragen