2016-08-19 47 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)