2015-06-04 9 views
5

Mam ten fragment kodu w moim API, który niedawno stał się nieco gardłem:Django: Jak policzyć zestaw zapytań i zwrócić plaster, nie uderzając dwukrotnie w DB?

total = results.count() 
if request.GET.has_key('offset'): 
    offset = int(request.GET.get('offset').strip()) 
    results = results.order_by('name')[100*offset:100*(offset+1)] 
people = list(results) 

Zauważ, że results jest queryset wszystkich ludzi i offset param jest stosowany do paginacji.

Tutaj mogę zobaczyć, kiedy wydrukuję connection.queries, że moja baza danych zostanie dwukrotnie trafiony przez .count() i list(results). Powód, dla którego .count() musi być na górze, ponieważ potrzebuję do tego całej długości ludzi (nie 100.) Czy istnieje sposób na obejście tego?

+2

Gdzie dokładnie używasz słowa "total"? – Jkdc

+1

[MySQL może to zrobić] (https://stackoverflow.com/a/2439870/1248008), ale nie wiem jak tego użyć przy użyciu django i nie jestem pewien, czy inne bazy danych obsługują to. –

+0

@ JonasWielicki Jest dyskusyjne, czy to jeszcze przyspieszy rzeczy; zobacz: https://www.percona.com/blog/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/ - lepszym sposobem rozwiązania tego problemu może być najpierw zrozumienie, dlaczego te zapytania są zbyt długo. Odpowiednie wskaźniki mogą Ci pomóc. –

Odpowiedz

0

Może coś takiego ?:

allpeople = list(results.order_by('name')) 
total = len(allpeople) 
if request.GET.has_key('offset'): 
    offset = int(request.GET.get('offset').strip()) 
    results = allpeople[100*offset:100*(offset+1)] 
people = results 

Należy pamiętać, że z people = results będzie zawodzić, jeśli if request.GET....: nie uruchamia.

+1

Możesz zainicjować wyniki, takie jak 'results = allpeople = list (results ...) w pierwszym wierszu, aby usunąć potrzebę ostatecznego zastrzeżenia. –

+5

Nie zgadzam się z tą odpowiedzią, ponieważ nie znamy liczby zwracanych wyników.Zawijając zestaw kwerendy w 'list()' powoduje, że jest on oceniany, i przynosi wszystkie wyniki do pamięci.Jeśli masz kilka milionów wyników, to może Zdarzyło mi się to ostatnio, więc mówię z doświadczenia –

+0

Masz rację, to jest tak naprawdę wolniejsze, ponieważ porównałem je z milionami rekordów, ale całkowicie odpowiada na pytanie, jak uniknąć dwukrotnego trafienia w DB. .. Okazało się @ThomasOrozco miał rację, że mniej queri es nie zawsze może być szybsze. Btw, indeks 'name' zawsze był obecny od samego początku. –

Powiązane problemy