我有类似的Django代码:
for obj in some_list:
m1obj = Model1.objects.get(a=obj.a, b=obj.b, c=obj.c)
Model2(m1=m1obj, d=obj.d, e='foo').save()
我确实使用Model2
优化插入bulk_create
,然而,由于来自get
的{{1}}( ~45秒对于3k插入物。)
我也尝试添加:
Model1
class Meta:
index_together = [
('a', 'b', 'c'),
]
unique_together = [
('a', 'b', 'c'),
]
有点帮助,unique_together
似乎没什么影响。
我有一个繁琐的解决方法:
index_together
以一个或多个键获取我需要的所有对象,例如Model1
,并确保Django缓存结果,例如order_by('a', 'b')
len()
)找到第一个from bisect import bisect_left
然后找到a
...等(尽管b
和b
更少s所以只是迭代是一样的。这会将插入时间减少到超过 3秒!
必须有更好,更清洁和可维护的方法来做到这一点。有什么建议? 有没有办法在Django的缓存查询结果中过滤/获取(聪明地)?
编辑:将c
更改为d='foo'
- 任何批量获取都需要映射到它所属的元组,否则我无法创建Model2条目。
答案 0 :(得分:0)
您可以进行单个查询(如here所述),该查询只会获取您需要的结果,因此无需在以后进行排序和二进制搜索。
我没有测试过,所以我不知道它是否会比你现在做的更快。此外,由于SQL查询会很大(根据some_list
中的记录数),因此如果查询超出MySQL设置中参数max_allowed_packet
定义的大小,则此查询可能会引发错误(默认情况下为16MB {} 3}})。
import operator
from django.db.models import Q
query = reduce(operator.or_, (Q(a=obj.a, b=obj.b, c=obj.c) for x in values))
model1_objs = Model1.objects.filter(query)
然后,您可以使用bulk_create
进行Model2
。
Model2.objects.bulk_create([
Model2(m1=m1, d='foo', e='bar')
for m1 in model1_objs
])
答案 1 :(得分:0)
Model1有多少行?如果它相对较小(小于50k)你可以使用过滤器获取所有,然后比较python中的元组。
“some_list”如何是小列表(小于100),如果是,你可以使用Q关键字一次过滤所有内容。
first = some_list.pop()
conditions = Q(a=first.a, b=first.b, c=first.c)
for obj in some_list:
conditions |= Q(a=obj.a, b=obj.b, c=obj.c)
Model1.objects.filter(conditions) # this will get your all the Model1 from ur list
Q object Ref:https://docs.djangoproject.com/en/1.9/ref/models/querysets/#q-objects