Django:使用过滤器随机查询一条记录的最快方法

时间:2017-07-13 17:17:12

标签: python mysql django algorithm

从数据库中查询满足我的过滤器查询的一条记录的最快方法是什么。

mydb.objects.filter(start__gte='2017-1-1', status='yes').order_by('?')[:1]

此语句将首先查询数千条记录然后选择一条记录,并且速度非常慢,但我只需要一条记录,一条随机记录。什么是最快的?

2 个答案:

答案 0 :(得分:2)

使用order_by('?')会导致性能问题。更好的方法是使用以下内容:Getting a random row from a relational database.

count = mydb.objects.filter(start__gte='2017-1-1', status='yes').aggregate(count=Count('id'))['count']
random_index = randint(0, count - 1)
result= mydb.objects.filter(start__gte='2017-1-1', status='yes')[random_index]

答案 1 :(得分:1)

嗯,我不确定你能不能做到你想要的。几个月前我遇到了类似的问题,最后我重新设计了我的后端实现,以使其工作。

基本上,您希望通过选择满足两个要求的随机记录(start__gte='2017-1-1', status='yes')来缩短查询时间,但就像您说的那样,为了使查询能够这样做,它需要过滤您的整个数据库。这意味着你无法得到一个真实的"来自数据库的满足过滤器要求的随机记录,因为过滤本身需要查看所有记录(否则它不是真正随机的,它只是第一个它发现符合您的要求。)

相反,请考虑将具有status='yes'的所有记录放在单独的关系中,以便您可以从那里提取随机记录并加入更大的关系。这将使查询时间大大加快(并且它是我为实现代码而实现的解决方案类型)。

如果您真的想要一个包含正确过滤信息的随机记录,您可能需要使用一些复杂的方法。

您可以在Django中使用custom manager让它只找到一条随机记录,如下所示:

class UsersManager(models.Manager):
    def random(self):
        count = self.aggregate(count=Count('id'))['count']
        random_index = randint(0, count - 1)
        return self.all()[random_index]

class User(models.Model):
    objects = UsersManager()
    #Your fields here (whatever they are, it seems start__gte and status are some)!
    objects = UserManager()

您只需使用以下内容即可调用:

User.objects.random()

可以通过检查代码重复此操作,直到它返回满足您要求的随机记录。我认为这不一定是实现这一目标的最简洁或最正确的方法,但我不认为对于您的具体问题存在更快的解决方案。

我使用this site作为此答案的来源,并且它有更多关于使用此自定义随机方法的可靠信息!您可能需要更改自定义管理器以满足您自己的需求,但如果您将random()方法添加到现有的自定义管理器,它应该能够满足您的需求!

希望它有所帮助!