Подтвердить что ты не робот

Django haystack whoosh супер медленный

У меня простая настройка с django-haystack и движком whoosh. Поиск с 19 объектами занял у меня 8 секунд. Я использовал панель инструментов django-debug, чтобы определить, что у меня была куча повторяющихся запросов.

Затем я обновил свое поисковое представление для отношений предварительной выборки, чтобы дублировать запросы не удавалось:

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')
    )

Но даже тогда поиск по-прежнему занимает 5 секунд. Затем я использовал профайлер из django-debug-toolbar, который дал мне эту информацию:

Результаты профайла панели инструментов отладки Django

Из того, что я могу сказать, проблема заключается в haystack/query:779::__getitem__, который дважды попадает, каждый стоит 1,5 секунды. Я просмотрел этот код, но не могу понять. Итак, куда мне идти?

4b9b3361

Ответ 1

Вы говорите в вопросе:

Затем я обновил свое окно поиска, чтобы предварительно выбрать отношения [...]

Приведенный вами код, однако, не использует QuerySet.prefetch_related для большинства из них. Вместо этого ваш пример кода использует QuerySet.select_related для большинства из них; это не обеспечивает предварительную выборку объектов.

Документация по каждому из этих методов обширна и может помочь решить, что правильно для вашего случая.

В частности, документация QuerySet.prefetch_related говорит:

select_related работает, создавая соединение SQL и включающее поля связанного объекта в инструкции SELECT. По этой причине select_related получает связанные объекты в одном запросе базы данных. Однако, чтобы избежать гораздо большего набора результатов, который возник бы в результате присоединения к "многим отношениям", select_related ограничивается однозначными отношениями - внешним ключом и взаимно однозначным.

prefetch_related, с другой стороны, выполняет отдельный поиск для каждой связи и выполняет "соединение в Python. Это позволяет ему предварительно выбирать объекты" многие-ко-многим "и" многие-к-одному ", которые не могут быть выполнены с помощью select_related, в дополнение к внешним ключам и отношениям" один-к-одному", которые поддерживаются select_related. Он также поддерживает предварительную выборку GenericRelation и GenericForeignKey, однако она должна быть ограничена однородным набором результатов. Например, предварительная выборка объектов, на которые ссылается GenericForeignKey, поддерживается только в том случае, если запрос ограничен одним ContentType.