对django queryset的缓慢迭代

时间:2014-09-16 05:41:23

标签: django optimization django-models iteration django-queryset

我正在迭代一个包含500-1000个对象的django查询集。相应的模型/表格中也有7个字段。问题是,在考虑需要在我的应用程序中完成的所有其他数据处理时,迭代过程需要大约3秒钟。

编辑: 这是我的模特:

    class Node(models.Model):
        node_id = models.CharField(null=True, blank=True, max_length=30)
        jobs = models.TextField(null=True, blank=True)
        available_mem = models.CharField(null=True, blank=True, max_length=30)
        assigned_mem = models.CharField(null=True, blank=True ,max_length=30)
        available_ncpus = models.PositiveIntegerField(null=True, blank=True)
        assigned_ncpus = models.PositiveIntegerField(null=True, blank=True)
        cluster = models.CharField(null=True, blank=True, max_length=30)
        datetime = models.DateTimeField(auto_now_add=False)

这是我的初始查询,速度非常快:

    timestamp = models.Node.objects.order_by('-pk').filter(cluster=cluster)[0]
    self.nodes = models.Node.objects.filter(datetime=timestamp.datetime)

然后,我去迭代,需要3秒,我尝试了两种方法,如下所示:

    def jobs_by_node(self):
    """returns a dictionary containing keys that
       are strings of node ids and values that
       are lists of the jobs running on that node."""
    jobs_by_node = {}

    #iterate over nodes and populate jobs_by_node dictionary
    tstart = time.time()
    for node in self.nodes:
        pass #I have omitted the code because the slowdown is simply iteration
    tend = time.time()
    tfinal = tend-tstart
    return jobs_by_node

其他方法:

    all_nodes = self.nodes.values('node_id')
    tstart = time.time()
    for node in all_nodes:
        pass
    tend = time.time()
    tfinal = tend-tstart

我通过引用this帖子尝试了第二种方法,但它仍然没有加快我的迭代速度。我在网上搜索无济于事。任何优化此过程的帮助将不胜感激。谢谢。

注意:我正在使用Django 1.5和Python 2.7.3

1 个答案:

答案 0 :(得分:1)

检查已发出的SQL查询。您可以使用print声明:

print self.nodes.query  # in general: print queryset.query

那应该给你一些:

SELECT id, jobs, ... FROM app_node

然后运行EXPLAIN SELECT id, jobs, ... FROM app_node,你就会知道到底出了什么问题。


假设您在运行EXPLAIN后知道问题是什么,并且添加索引这样的简单解决方案是不够的,您可以考虑例如每隔X分钟(在cron作业或Celery任务中)将相关行提取到单独的表,并在应用程序中使用该单独的表。

如果您正在使用PostgreSQL,您还可以使用materialized views并将其“换行”在unmanaged Django model中。