表现我设计一个data-tables
驱动的Django应用程序,并有data-tables
电话与AJAX(我使用其服务器端处理模式data-tables
)的API视图。它实现搜索,分页和排序。在Django视图状态保持改善分页
我的数据库最近变大了(大约500,000个条目),性能受到很大影响,无论是搜索还是转到下一页。我怀疑我写这个观点的方式是非常低效的。下面是我在视图中执行(假设在我的数据库中的对象是比萨):
filtered = Pizza.objects.filter(...)
获得一系列符合搜索条件的比萨饼。 (或者如果没有搜索标准,则为Pizza.objects.all()
)。paginated = filtered[start: start + length]
只得到当前的比萨饼页面。 (最多只有100个)。根据用户所在的页面,从data-tables
客户端代码传入开始和长度。pizzas = paginated.order_by(...)
将排序应用于当前页面。
然后我将pizzas
转换成JSON并从视图中返回它们。
看起来,尽管搜索对于500,000个条目来说可能是一个缓慢的操作,但移动到下一个页面不应该要求我们重做整个搜索。所以我想要做的是在视图中缓存一些东西(这是一个基于类的视图)。我会跟踪最后一个搜索字符串是什么,以及它生成的一组结果。
然后,如果请求通过并且搜索字符串没有不同(如果用户点击了几页结果,会发生什么情况),我不必再次点击数据库以获取过滤器结果 - 我只能使用缓存版本。
这是一个只读应用程序,所以不同步不会是一个问题。
我甚至可以保留一大堆搜索字符串和他们应该产生的比萨饼的字典。
我想知道的是:这是对问题的合理解决方案吗?还是有我忽略的东西?另外,我在这里重新发明车轮吗?这并不是说这不易实施,但是QuerySet
还有一个内置的选项,或者可以做到这一点?
哇,这是真的吗?如果我先切片查询集,然后做过滤/排序/无论它,它实际上是过滤/命令/任何然后切片? –
根据django 1.8的文档,“对未评估的QuerySet进行切片会返回另一个未评估的QuerySet,因此不允许对其进行进一步修改(例如,添加更多过滤器或修改排序)”。所以看起来我部分错了,'pizzas = paginated.order_by(...)'是不允许的。仍然“考虑将索引添加到您经常使用filter(),exclude(),order_by()查询的字段” – JimmyYe