2016-08-19 48 views
0

我知道我可以指定存储像这样的prefetch_related的结果。Django商店prefetch相关结果

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

这两者是相同的

MyClass.objects.prefetch_related('relation') 

MyClass.objects.prefetch_related(
    Prefetch('relation', to_attr='relation_as_list') 
) 

可以使用预取对象,以进一步控制预取操作(docs

你只需要当你需要一个Prefetch对象改进prefetch_related的结果。例如,你可能不需要每个relation,但是特定的,所以你可以改进预取查询。

使用to_attr建议过滤下来的时候预取结果,因为它比在相关管理器的缓存存储过滤结果更加明确(docs

to_attr不给额外的性能提升,它允许使关系更不明确,并且使得可以预取与不同的QuerySet相同的关系。

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') 
) 

如果预取不同Prefetch对象相同的关系,也将是他们每个人的其他查询。生成的预取QuerySets将存储在一个列表中,但结果不是像您假设为relation_as_list的列表。它们是QuerySets。在你的榜样,访问既关系可以用all()来完成,像my_obj.relation_as_list.all()my_obj.relation.all()

关于性能提升

综上所述,prefetch_related获取一个(附加)DB相关的对象打这哪里是性能提升来自于。使用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)