sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Por qué este recuento de anotaciones de Django (1.6) es tan lento?

Por qué es lento :Si simplemente usó la anotación por dos campos ManyToMany luego crea una gran unión no deseada de todas estas tablas juntos. El tamaño del producto cartesiano de filas que debe evaluarse es aproximadamente Have.objects.count() * Want.objects.count() . Entonces escribiste distinct=True para restringir finalmente la cantidad de elementos duplicados para no obtener un resultado enorme no válido.

Corrección para Django antiguo:si usara solo queryset.annotate(have_count=Count("have")) obtendrá el resultado correcto rápidamente sin distinct=True o el mismo resultado también rápido con distinto. Luego puede combinar los resultados de dos consultas de Python en la memoria.

Solución Una buena solución es posible en Django>=1.11 (dos años después de su pregunta) usando una consulta con dos subconsultas , uno para Have y uno para Want , todo por una solicitud, pero no para mezclar todas las tablas.

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 :Puede comprobar tanto la consulta SQL lenta como la fija imprimiendo str(my_queryset.query) que es como se describe arriba.