2015-08-24 11 views
13

Ich habe eine einfache Einrichtung mit Django-Heuhaufen und whoosh Motor. Eine Suche nach 19 Objekten dauerte 8 Sekunden. Ich benutzte die Django-Debug-Toolbar, um festzustellen, dass ich eine Reihe von wiederholten Abfragen hatte.Django Heuhaufen Whoosh super langsam

ich dann meine Suche auf Prefetch Beziehungen aktualisiert, so dass Abfragen duplizieren nicht passieren würde:

class MySearchView(SearchView): 
    template_name = 'search_results.html' 
    form_class = SearchForm 
    queryset = RelatedSearchQuerySet().load_all().load_all_queryset(
     models.Customer, models.Customer.objects.all().select_related('customer_number').prefetch_related(
      'keywords' 
     ) 
    ).load_all_queryset(
     models.Contact, models.Contact.objects.all().select_related('customer') 
    ).load_all_queryset(
     models.Account, models.Account.objects.all().select_related(
      'customer', 'account_number', 'main_contact', 'main_contact__customer' 
     ) 
    ).load_all_queryset(
     models.Invoice, models.Invoice.objects.all().select_related(
      'customer', 'end_customer', 'customer__original', 'end_customer__original', 'quote_number', 'invoice_number' 
     ) 
    ).load_all_queryset(
     models.File, models.File.objects.all().select_related('file_number', 'customer').prefetch_related(
      'keywords' 
     ) 
    ).load_all_queryset(
     models.Import, models.Import.objects.all().select_related('import_number', 'customer').prefetch_related(
      'keywords' 
     ) 
    ).load_all_queryset(
     models.Event, models.Event.objects.all().prefetch_related('customers', 'contracts', 'accounts', 'keywords') 
    ) 

Aber selbst dann die Suche dauert noch 5 Sekunden. Früher habe ich dann den Profiler von django-debug-toolbar, die mir diese Informationen gab:

Django debug toolbar profiler results

Von dem, was ich sagen kann, das Problem liegt in haystack/query:779::__getitem__, die zweimal getroffen wird, jeder kostet 1,5 Sekunden. Ich habe den fraglichen Code durchgesehen, kann aber keinen Sinn daraus machen. Wohin gehe ich von hier?

+2

Wie viele Objekte befinden Sie in Ihrem Suchindex? – phildini

+0

@phildini "19 Objekte" –

+2

Es scheint, als ob '__getitem__' 2 Abfragen an die Datenbank auslöst. Schauen Sie sich '_fill_cache' an, es ruft zweimal 'get_results' auf, was insgesamt etwa 3 Sekunden dauert. Sind Sie sicher, dass alle Artikel vorab von der Datenbank abgerufen wurden? –

Antwort

1

Sie sagen, in der Frage:

ich dann meine Suche nach Prefetch Beziehungen aktualisiert [...]

Der Code, den Sie präsentieren, aber nicht QuerySet.prefetch_related für die meisten von ihnen nicht verwendet. Stattdessen verwendet Ihr Beispielcode QuerySet.select_related für die meisten von ihnen; Dadurch werden die Objekte nicht vorab abgerufen.

Die Dokumentation für jede dieser Methoden ist umfangreich und kann helfen, zu entscheiden, welche für Ihren Fall richtig ist.

Insbesondere the QuerySet.prefetch_related documentation sagen:

select_related Werke, indem eine SQL verbinden und mit den Feldern des zugehörigen Objekts in der SELECT Aussage. Aus diesem Grund ruft select_related die zugehörigen Objekte in derselben Datenbankabfrage ab. Um jedoch die viel größere Ergebnismenge zu vermeiden, die sich aus dem Verbinden über eine "viele" Beziehung ergeben würde, ist select_related auf einwertige Beziehungen beschränkt - Fremdschlüssel und Eins-zu-Eins.

prefetch_related, führt auf der anderen Seite eine separate Suche für jede Beziehung durch und führt das "Verbinden" in Python durch. Dies ermöglicht das Vorabholen von Viele-zu-Viele- und Viele-zu-Eins-Objekten, die nicht mit select_related durchgeführt werden können, zusätzlich zu den Fremdschlüssel- und Eins-zu-Eins-Beziehungen, die von select_related unterstützt werden. Es unterstützt auch Vorabruf von GenericRelation und GenericForeignKey, jedoch muss es auf eine homogene Reihe von Ergebnissen beschränkt werden. Beispielsweise wird das Vorabholen von Objekten, auf die von einer GenericForeignKey verwiesen wird, nur unterstützt, wenn die Abfrage auf eine ContentType beschränkt ist.

Verwandte Themen