尝试最小化数据库投票表的访问次数

时间:2016-09-21 16:45:48

标签: django postgresql redis django-cache

我使用django 1.10.1,postgres 9.5和redis。 我有一个存储用户投票的表格,如下所示:

==========================
object | user | created_on
==========================

其中objectuser分别是其各自表的id列的外键。

问题是在许多情况下,我必须在一个页面中列出许多对象。如果用户已登录或经过身份验证,我必须检查每个对象是否已被投票(并根据结果执行操作,例如显示voteunvote按钮)。所以在我的模板中,我必须为页面中的每个对象调用这样的函数。

def is_obj_voted(obj_id, usr_id):
    return ObjVotes.objects.filter(object_id=obj_id, user_id=usr_id).exists()

由于我在一个页面中可能有数十个对象,因此我发现,使用django-debug-toolbar,单独访问数据库可能需要一秒多的时间,因为我只为每个查询访问一行,并且这是在一个串行中发生的方式为页面中的所有对象。更糟糕的是,我在其他页面中使用来自该表的类似查询(即仅使用user或仅使用object进行过滤)。

我尝试实现的目标以及我认为正确的做法是找到一种方法来访问数据库一次,以获取由某个用户过滤的所有对象(可能是在用户登录时或者在第一页命中需要这样的数据库访问),然后根据页面需要将其进一步过滤到我想要的任何内容。由于我使用redis和django-cacheops应用程序,它可以帮助我完成这项工作吗?

1 个答案:

答案 0 :(得分:0)

在您的情况下,我最好使用一组对象ID并按用户的ID和此数组查询所有投票,例如:

object_ids = [o.id for o in Object.objects.filter(YOUR CONDITIONS)]
votes = set([v.object_id for v in ObjVotes.objects.filter(object_id__in=object_ids, user_id=usr_id)]
def is_obj_voted(obj_id, votes):
    return obj_id in votes

这将只使用一个额外的数据库查询来获取每页用户的投票。