我知道我可以指定存储prefetch_related的结果。
my_objs = MyClass.objects.prefetch_related(
Prefetch('relation', to_attr='relation_as_list')
)
for my_obj in my_objs:
l = my_obj.relation_as_list
与以下相同吗? Doc说prefetch_related商店会产生Queryset,而我无法获得提升性能的地方吗?
my_objs = MyClass.objects.prefetch_related('relation')
for my_obj in my_objs:
l = list(my_obj.relation.all()) # looks like DB hit but it isnt?
答案 0 :(得分:0)
这两个是相同的
MyClass.objects.prefetch_related('relation')
MyClass.objects.prefetch_related(
Prefetch('relation', to_attr='relation_as_list')
)
您可以使用Prefetch对象进一步控制预取操作(docs)
仅当您需要优化Prefetch
的结果时,才需要prefetch_related
个对象。例如,您可能不需要每个relation
但需要特定的to_attr
,因此您可以优化预取查询。
在过滤预取结果时建议使用to_attr,因为它比将过滤结果存储在相关管理器缓存(docs)
中更不明确
Prefetch
不会提供额外的性能提升,它可以使MyClass.objects.prefetch_related(
Prefetch('same_relation', queryset=queryset_one, to_attr='relation_set_one')
Prefetch('same_relation', queryset=queryset_two, to_attr='relation_set_two')
)
关系不那么模糊,并且可以使用不同的QuerySet预取相同的关系。
Prefetch
如果您使用不同的relation_as_list
对象预取相同的关系,则每个对象都会有一个额外的查询。生成的预取QuerySet将存储在列表中,但结果不是您假设为all()
的列表。它们是QuerySet。在您的示例中,可以使用my_obj.relation_as_list.all()
访问这两种关系,例如my_obj.relation.all()
和prefetch_related
关于提升效果
总之,Prefetch
在一个(额外的)数据库命中中获取相关对象,这是性能提升的来源。 for item in yourmodel.object.all():
for a_relation in item.relation.all():
do_something(a_relation)
# WITHOUT PREFETCH RELATED YOU'D HIT DB EVERY TIME!!
# IMAGINE IF YOU HAD TONS OF ITEMS
# THIS WILL HAVE 2 DB HITS
for item in yourmodel.object.prefetch_related('relation').all().:
for a_relation in item.relation.all():
do_something(a_relation)
个对象可让您进一步优化此数据库调用。
var watermark_action = actions.create("pdf-watermark");
watermark_action.parameters["inplace"] = true;
watermark_action.parameters["destination-folder"] = document.parent;
watermark_action.parameters["watermark-type"] = "text";
watermark_action.parameters["watermark-text"] = "Lorem Ipsum";
watermark_action.parameters["watermark-font"] = "Helvetica";
watermark_action.parameters["watermark-size"] = "14";
watermark_action.parameters["page"] = "all";
watermark_action.parameters["watermark-depth"] = "over";
watermark_action.parameters["position"] = "center";
watermark_action.execute(document);