Mengapa lambat :Jika Anda hanya menggunakan anotasi oleh dua bidang ManyToMany lalu Anda membuat gabungan besar yang tidak diinginkan dari semua tabel ini bersama. Ukuran produk Cartesian dari baris yang harus dievaluasi kira-kira Have.objects.count() * Want.objects.count()
. Anda kemudian menulis distinct=True
untuk membatasi akhirnya jumlah item yang digandakan agar tidak mendapatkan hasil besar yang tidak valid.
Perbaiki untuk Django lama:Jika Anda hanya akan menggunakan queryset.annotate(have_count=Count("have"))
Anda akan mendapatkan hasil yang tepat dengan cepat tanpa distinct=True
atau hasil yang sama juga cepat dengan perbedaan. Kemudian Anda dapat menggabungkan hasil dua kueri dengan Python di memori.
Solusi Solusi yang bagus dimungkinkan di Django>=1.11 (dua tahun setelah pertanyaan Anda) dengan menggunakan kueri dengan dua subkueri , satu untuk Have
dan satu untuk Want
, semua dengan satu permintaan, tetapi tidak untuk mencampur semua tabel menjadi satu.
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))
Verifikasi :Anda dapat memeriksa kueri SQL yang lambat dan tetap dengan mencetak str(my_queryset.query)
bahwa itu seperti yang dijelaskan di atas.