我有一个函数,它对许多对象进行大量的数据库查询:
def some_func(user):
group1 = user.manytomanyfield1.all()
allinstances = []
for item in group1:
allinstances += group1.manytomanyfield2.all()
然后我有一个列表'所有实例',这是复合的对象。然后,我需要检查创建的'allinstances'列表是否具有属性'name'的对象,该对象在'allinstances'列表中的一些对象中相同,并删除重复项:
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
当所有实例的大小都很小时,函数执行得非常快。但我的应用范围是这样的,它通常会与数万甚至数十万的"object1"一起工作,所以"allinstances"列表将是巨大的,所以函数执行将花费很长时间。目前,在'allinstances'中有25000个'object1',函数执行需要10秒。这对我来说是无法承受的,因为返回的列表进一步被放入Paginator,并且从结果构造具有object1详细信息的Listview,因此用户必须在函数执行时等待。
我看到以下选项可以减少这个瓶颈:1. 优化函数执行速度2. 更改我的视图以使用AJAX,并将函数执行重路由到像芹菜这样的异步任务队列。然后,页面上的AJAX每隔一段时间查询结果,当任务完成时将结果添加到页面上。
在这种情况下有什么最佳做法吗?也许还有其他更可行的解决方案?欢迎提出任何代码改进建议。一个非常快速的优化将使names
成为一个集合,因为列表查找是线性的(O(n)),而集合查找是恒定的(O(1)):
names = set()
doubleList = []
for number, object1 in enumerate(allinstances):
if object1.name not in names:
names.add(object1.name)
我认为你的很多性能问题都来自于当你有很多记录时,Django必须运行大约25000个查询。
prefetch_related是我在这里使用的。
代码的第一部分看起来像这样:
def some_func(user):
group1 = user.manytomanyfield1.all().prefetch_related('manytomanyfield2')
allinstances = []
for item in group1:
allinstances += item.manytomanyfield2.all()