Django 分页对于大型数据集速度太慢

9

我有一个关于Django分页的问题。当我尝试分页超过20万条记录时,网站加载非常慢(>10秒),而且我应该使用大约200万条记录。

我在Stackoverflow或其他网站上找不到针对此问题的好解决方法。每次代码获取页面时,它都会执行QuerySet,这需要处理一个非常大的数据集,使其变得缓慢。

有人知道应该怎么做吗?我已经到处搜索了,但无法解决这个问题。以下是分页代码。Paper_list是:model.object.all().filter(category=x)(现在大约有20万个对象(它们都属于该类别)。

def paginate_context(paper_list, request, context, source, author, title, term, date):
num_papers = len(paper_list) 
paginator = Paginator(paper_list, 4) # Show X papers per page
page = request.GET.get('page')
try:
    papers = paginator.page(page)
except PageNotAnInteger:
    # If page is not an integer, deliver first page.
    papers = paginator.page(1)
except EmptyPage:
    # If page is out of range (e.g. 9999), deliver last page of results.
    papers = paginator.page(paginator.num_pages)      
context['papers'] = papers
context['num_papers'] = num_papers
context['query_cat'] = create_request_str_and(context['cat'], source, author, title, term, date)

你在排序查询集或筛选时,所用的字段是否设置了索引? - Alex Morozov
我定义了一个类别为models.CharField(db_index=True, max_length=200)的变量。我知道计数可能会有问题,但我尝试了一些方法来修复它,但没有太大的成功。 - E.Diaz
你能查一下实际的数据库查询语句(并对其进行EXPLAIN SELECT吗?也许将category字段转换为ForeignKey值得一试,但这只是一个猜测。 - Alex Morozov
我在SELECT之前使用了EXPLAIN查询。但是我不确定如何解释它的结果。在EXPLAIN SELECT之后: | category | NULL | index | NULL | category_1da45b5bea657362_uniq | 602 | NULL | 112172 | 100.00 | Using index | +----+-------------+-------------------------------+------------+-------+---------------+--------------- 结果集中有1行,1个警告(0.00秒)。 - E.Diaz
我的意思是,你应该解释慢查询,而不是空的SELECT。如果你使用Postgresql,有一个方便的服务:http://explain.depesz.com/。或者你提供的结果是实际的解释结果吗?请通过dpaste或gist发布它,因为它很难阅读。 - Alex Morozov
我正在使用mySQL。也许我没有正确地解释自己。当我直接在mySQL上运行查询时,它只需要0.07秒就能执行(带有索引)。但是当我使用分页时,网站和分页运行非常缓慢。每次获取新页面时,加载需要很多秒。有人告诉我这可能是因为每个请求的页面都会执行一个查询。 - E.Diaz
1个回答

4

2
鲁德拉,鹰眼!)那绝对是真正的问题。 - Alex Morozov
那只是一行信息代码,用于显示有多少结果。我被告知这可能会影响性能,所以我评论了那一行。问题仍然存在。我尝试了你之前建议的方法,但它没有改善加载时间。 - E.Diaz
没关系。那确实解决了问题。谢谢!现在我又有了一个问题。model.objects.all().filter(category=context['cat'])没有返回所有应该返回的记录,因为它只返回具有1个类别的记录。但是每个记录可以有多个相关联的类别。这个可以工作:[item for item in model.objects.all() if any(category in item.category for category in context['cat'])] 但执行时间太慢了。 - E.Diaz
如果您能就新问题提出另一个问题,那会更清晰明了 :)。请接受我的答案,这将有助于未来其他人的解决方案 :)。 - ruddra
1
等系统允许我发布新问题时,我会再发一个。因为我之前尝试修复这个问题并没有取得太大的成功(因此使用了过度工作的for()来获取正确的记录)。感谢您的回答。 - E.Diaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接