Django存储prefetch_相关结果

eug*_*ene 2 django prefetch

我知道我可以指定像这样存储 prefetch_lated 的结果。

 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
Run Code Online (Sandbox Code Playgroud)

是不是和下面的一样呢?文档说 prefetch_lated 存储导致查询集,但我不明白我在哪里获得性能提升?

 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?
Run Code Online (Sandbox Code Playgroud)

Tin*_*nce 8

这两个是一样的

\n\n
MyClass.objects.prefetch_related(\'relation\')\n\nMyClass.objects.prefetch_related(\n   Prefetch(\'relation\', to_attr=\'relation_as_list\')\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

您可以使用 Prefetch 对象进一步控制预取操作(文档

\n
\n\n

Prefetch仅当您需要细化 的结果时才需要对象prefetch_related。例如,您可能不需要除relation特定之外的所有查询,因此您可以优化预取查询。

\n\n
\n

在过滤预取结果时,建议使用 to_attr,因为它比将过滤结果存储在相关 manager\xe2\x80\x99s 缓存中更明确(文档

\n
\n\n

to_attr不会带来额外的性能提升,它允许使Prefetch关系不那么模糊,并且可以使用不同的查询集预取相同的关系。

\n\n
MyClass.objects.prefetch_related(\n   Prefetch(\'same_relation\', queryset=queryset_one, to_attr=\'relation_set_one\')\n   Prefetch(\'same_relation\', queryset=queryset_two, to_attr=\'relation_set_two\')\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您预取与不同Prefetch对象的相同关系,则每个对象都会有一个额外的查询。生成的预取查询集将存储在列表中,但结果不是像您假设的那样的列表relation_as_list。它们是查询集。在您的示例中,可以使用all(), likemy_obj.relation_as_list.all()和来访问这两个关系my_obj.relation.all()

\n\n

关于性能提升

\n\n

总之,prefetch_related在一次(额外的)数据库命中中获取相关对象,这就是性能提升的来源。Prefetch对象可让您进一步细化此数据库调用。

\n\n
for item in yourmodel.object.all():\n    for a_relation in item.relation.all():\n        do_something(a_relation)  \n        # WITHOUT PREFETCH RELATED YOU\'D HIT DB EVERY TIME!! \n        # IMAGINE IF YOU HAD TONS OF ITEMS\n\n# THIS WILL HAVE 2 DB HITS\nfor item in yourmodel.object.prefetch_related(\'relation\').all().:\n    for a_relation in item.relation.all():\n        do_something(a_relation)  \n
Run Code Online (Sandbox Code Playgroud)\n