Django重型数据库查询和数据处理

时间:2014-07-31 17:25:50

标签: python ajax django optimization celery

我有一个函数可以跨多个对象执行大量的数据库查询:

def some_func(user):
    group1 = user.manytomanyfield1.all()
    allinstances = []
    for item in group1:
        allinstances += group1.manytomanyfield2.all()

然后我有一个列表' allinstances'这是对象的复合。然后,我需要检查创建的' allinstances' list包含具有属性&name; name'这对于所有实例中的一些对象是相同的。列出并删除重复项:

    names = []
    doubleList = []
    for number, object1 in enumerate(allinstances):
        if object1.name not in names:
            names.append(object1.name)
        else:
            doubleList.append(number)
    doubleList.reverse()
    for item in doubleList:
    allinstances.pop(item)
return allinstances

当所有实例的大小很小时,该功能执行得非常快。但我的应用程序范围是这样的,它最常见的工作量可能是数万,可能是数十万个对象1所以'所有实例' list会很大,所以函数执行会花费很长时间。目前有~25000'对象1' allinstances'函数执行需要10秒。这对我来说是负担不起的,因为返回的列表进一步被放入Paginator中,并且具有object1的详细信息的Listview是根据结果构造的,因此用户必须在函数执行时等待。

我看到以下选项可以减少这个瓶颈: 1.优化功能执行速度 2.更改我的视图以使用AJAX并将函数执行重新路由到异步任务队列,如Celery。然后页面上的AJAX会在某些时间间隔内查询结果,当任务完成时,会在页面上添加结果。

在这种情况下是否有最佳做法? 也许还有其他更可行的解决方案? 欢迎任何代码改进建议。

2 个答案:

答案 0 :(得分:1)

一个非常快速的优化是使names成为一个集合,因为列表查找是线性的(O(n))而set set是常量的(O(1)):

names = set()
doubleList = []
for number, object1 in enumerate(allinstances):
    if object1.name not in names:
        names.add(object1.name)

答案 1 :(得分:0)

我认为你的很多性能问题来自Django,当你有大量记录时,必须运行~25000个查询。

prefetch_related就是我在这里使用的。

代码的第一部分如下所示:

def some_func(user):
    group1 = user.manytomanyfield1.all().prefetch_related('manytomanyfield2')
    allinstances = []
    for item in group1:
         allinstances += item.manytomanyfield2.all()