【问题标题】:Django ListView painfully slow using Haystack使用 Haystack 的 Django ListView 非常慢
【发布时间】:2013-05-21 13:02:59
【问题描述】:

如何加快由Haystack-search 驱动(使用 Whoosh 后端)分页的 Django 列表视图?

我有一个简单的 ListView,例如:

class PersonListView(ListView)
    template_name = 'person-list.html'
    paginated_by = 10
    def get_queryset(self):
        return Person.objects.all()

返回一个包含 3000 个结果的页面在我的本地主机上运行大约 1 秒。

然后我“插入”Haystack 以允许对姓名进行全文搜索:

class PersonListView(ListView)
    template_name = 'person-list.html'
    paginated_by = 10
    def get_queryset(self):
        #return Person.objects.all()
        return SearchQuerySet().models(models.Person)

我设置了适当的索引并运行manage.py rebuild_index

class PersonIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    nickname = indexes.CharField()
    first_name = indexes.CharField()
    middle_name = indexes.CharField()
    last_name = indexes.CharField()

    def get_model(self):
        return models.Person

    def index_queryset(self, using=None):
        return self.get_model().objects.all()

然而,在这之后,同一个页面现在需要大约 15 秒才能运行...

我尝试使用django profiler,但我没有看到更改前后的查询时间有太大差异,并且运行时间最长的查询只需要一秒钟,这表明视图端存在一些导致所有问题的错误要迭代的查询结果。

是什么导致 Haystack 运行缓慢?

【问题讨论】:

    标签: python django django-haystack


    【解决方案1】:

    搜索速度慢的一个原因是,对于每个搜索结果,haystack 都会尝试从数据库中获取相应的对象。您可以通过在SearchQuerySet 上使用load_all() 来防止这种行为。然后 haystack 将尝试在一个查询中收集所有结果。在显示来自相关模型的内容时要小心,因为这会导致额外的数据库查找而无需任何额外的配置。

    如果您想避免一般的数据库查找和only display data that is indexed(您也可以尝试这样做以确保速度缓慢是由额外的数据库查找引起的)。 否则,如果您需要额外的调试,请使用 debug-toolbar,它将显示所有数据库查询,并且还有一个额外的 haystack 面板。

    【讨论】:

    • @Cerin 你能不能也提供一些你的模板代码,以便我们看到你是如何输出它的?
    【解决方案2】:

    根据this Haystack issue,您可以做两件事。

    第一个,可以在设置中将INCLUDE_SPELLING设置为False,如:

    HAYSTACK_CONNECTIONS = {
        'default': {
            'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
            'PATH': os.path.join(PATH_TMP, "whoosh_index", "default"),
            'STORAGE': 'file',
            'POST_LIMIT': 128 * 1024 * 1024,
            'INCLUDE_SPELLING': False,
            'BATCH_SIZE': 100,
        },
    }
    

    另一件事是您可以将HAYSTACK_ITERATOR_LOAD_PER_QUERY 设置为更大的数字,例如100 而不是默认的10

    HAYSTACK_ITERATOR_LOAD_PER_QUERY = 100
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多