Django存储prefetch_related结果

时间:2016-08-19 02:23:50

标签: django prefetch

我知道我可以指定存储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?

1 个答案:

答案 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);