2016-02-02 14 views
6

Istnieją dwa modele o relacji jeden do wielu, A -> {B}. Liczę ile rekordów A mam z tym samym B po użyciu filtra(). Następnie muszę wyodrębnić najlepsze rekordy X z A pod względem większości rekordów B z nimi połączonych.Django: alternatywa dla używania adnotacji (liczba()) dla prędkości

Obecny kod:

class A(models.Model): 
    code = models.IntegerField() 
    ... 

class B(models.Model): 
    a = models.ForeignKey(A) 
    ... 

data = B.objects.all().filter(...) 

top = data.values('a',...).annotate(n=Count('a')).distinct().order_by('-n')[:X]; 

mam ~ 300K B rekordy iz moim laptopie to bierze ~ 2s dla jednego zapytania. Rozłożyłem zapytanie na części i ustaliłem je w czasie, i wydaje się, że głównym wąskim gardłem jest adnotacja().

Czy jest jakiś sposób, aby to zrobić szybciej z Django?

Odpowiedz

0

Powinieneś dodać .select_related('a') przed annotate w zapytaniu. Zmusi to django do dołączenia do modeli przed ich zliczeniem.

https://docs.djangoproject.com/en/1.9/ref/models/querysets/#select-related

+0

Jeśli to zrobić przed wartościami() call (po niemożliwe), czas pozostaje w przybliżeniu taka sama. Czy też miałeś na myśli, że muszę to zrobić przed filtrem(), a wtedy grupa połączeń będzie szybsza? – user1581390

+0

Czy próbowałeś spojrzeć na SQL za pomocą 'print (data.sql)'? – onlythefinestwilldo