在Django视图中保持状态以提高分页性能

2024-05-20 02:28:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在设计一个data-tables驱动的Django应用程序,并且有一个用AJAX调用的API视图(我在服务器端处理模式中使用data-tables)。它实现搜索、分页和排序。在

我的数据库最近变得很大(大约500000个条目),性能受到很大影响,无论是搜索还是简单地移动到下一个页面。我怀疑我写这个观点的方式非常低效。下面是我在视图中的操作(假设数据库中的对象是pizza):

  • filtered = Pizza.objects.filter(...)以获取与搜索条件匹配的比萨饼集。(或者Pizza.objects.all(),如果没有搜索条件)。

  • paginated = filtered[start: start + length]只获取当前页面的比萨饼。(最多只有100个)。{根据客户端}的长度,{1从客户端开始传递}。

  • pizzas = paginated.order_by(...)将排序应用于当前页。

然后我将pizzas转换为JSON并从视图中返回它们。在

看起来,虽然搜索对500000个条目可能是一个缓慢的操作,但是仅仅移动到下一个页面不应该要求我们重做整个搜索。所以我想做的是在视图中缓存一些东西(这是一个基于类的视图)。我会跟踪上一个搜索字符串是什么,以及它产生的结果集。在

然后,如果一个请求通过并且搜索字符串没有变化(如果用户点击几页结果就会发生这种情况),我就不必再次访问数据库来获得过滤的结果——我可以使用缓存的版本。在

它是一个只读的应用程序,所以不同步不是问题。在

我甚至可以保存一本字典,里面有一大堆搜索字符串和他们应该制作的比萨饼。在

我想知道的是:这是解决问题的合理方法吗?还是我忽略了什么?还有,我是不是在重新发明轮子?这并不是说这不容易实现,而是在QuerySet上有一个内置的选项或其他方法来实现吗?在


Tags: 字符串视图数据库应用程序tablesdataobjects排序
2条回答

有多种方法可以改善代码结构

第一种方法是使用Django ORM hit只获取根据页码所需的数据,第二种方法是缓存ORM输出并在再次传递相同查询时重用该结果。在

首先是这样。

在你的代码里

Pizza.objects.all() paginated = filtered[start: start + length] 首先获取所有数据,然后将其切片,这是非常昂贵的SQL查询,然后将其转换为

filtered = Pizza.objects.all()[(page_number-1) * 30, (page_number-1) * 30 + 30]

上面给定的ORM将只获取那些根据所提供的页码的行,与获取所有行并对其进行切片相比,这是非常快的。在

第二种方法,首先根据查询取数,缓存方案如memcache或redis,下次需要从数据库中取数据时,先检查该查询的缓存中是否有数据,如果有,则直接使用该数据,因为内存缓存解决方案比从数据库中获取数据要快得多,因为内存和硬盘之间的输入输出传输非常大,而且我们知道传统上硬盘的速度很慢。在

pizzas = paginated.order_by(...)速度很慢,它对所有比萨饼进行排序,而不是对当前页面进行排序。索引帮助:https://docs.djangoproject.com/en/1.8/topics/db/optimization/#use-standard-db-optimization-techniques

如果你真的想要缓存,签出https://github.com/Suor/django-cacheops,“一个灵活的应用,支持自动或手动查询集缓存和自动粒度事件驱动的失效。”

相关问题 更多 >