PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Por que essa contagem de anotações do Django (1.6) é tão lenta?


Por que é lento :Se você simplesmente usou a anotação por dois campos ManyToMany então você cria uma grande junção indesejada de todas essas tabelas juntos. O tamanho do produto cartesiano de linhas que devem ser avaliadas é aproximadamente Have.objects.count() * Want.objects.count() . Você escreveu então distinct=True para restringir finalmente o número de itens duplicados para não obter um resultado enorme inválido.

Correção para o antigo Django:Se você usar apenas queryset.annotate(have_count=Count("have")) você obterá o resultado certo rapidamente sem distinct=True ou o mesmo resultado também rápido com distintos. Então você pode combinar os resultados de duas consultas por Python na memória.

Solução Uma boa solução é possível no Django>=1.11 (dois anos após sua pergunta) usando uma consulta com duas subconsultas , um para Have e um para Want , tudo por uma solicitação, mas não para misturar todas as tabelas.
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))

Verificar :Você pode verificar a consulta SQL lenta e fixa imprimindo str(my_queryset.query) que seja como descrito acima.