Django干草堆飞快超级慢

时间:2015-08-24 13:16:48

标签: python django profiling django-haystack whoosh

我有一个简单的设置与django-haystack和嗖嗖引擎。搜索产生19个物体花了我8秒钟。我使用django-debug-toolbar确定我有一堆重复的查询。

然后我将我的搜索视图更新为预取关系,以便不会发生重复查询:

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 debug toolbar profiler results

据我所知,问题在于haystack/query:779::__getitem__,它被击中两次,每次耗费1.5秒。我浏览过有问题的代码,但无法理解它。那么我从哪里开始呢?

2 个答案:

答案 0 :(得分:1)

你在问题​​中说:

  

然后我将搜索视图更新为预取关系[...]

但是,您提供的代码对大多数代码不使用QuerySet.prefetch_related。相反,您的示例代码对大多数代码使用QuerySet.select_related;这不会预取对象。

每种方法的文档都很广泛,可以帮助确定哪种方法适合您的情况。

特别是,the QuerySet.prefetch_related documentation说:

  

select_related通过创建SQL连接并在SELECT语句中包含相关对象的字段来工作。因此,select_related在同一数据库查询中获取相关对象。但是,为了避免加入“多”关系会产生更大的结果集,select_related仅限于单值关系 - 外键和一对一。

     另一方面,

prefetch_related对每个关系进行单独查找,并在Python中进行“加入”。这允许它预取多对多和多对一对象,除了{{1}支持的外键和一对一关系之外,这些对象无法使用select_related完成。 }。它还支持预取select_relatedGenericRelation,但必须将其限制为一组同类结果。例如,仅当查询限制为一个GenericForeignKey时,才支持预取GenericForeignKey引用的对象。

答案 1 :(得分:0)

尝试添加

HAYSTACK_LIMIT_TO_REGISTERED_MODELS = False

到您的settings.py。根据码头,

'如果您的搜索索引仅用于Haystack所注册的型号,则可以将其关闭,并获得小到中等的性能提升。'

它为我的项目缩短了3-4秒