我知道我可以指定像这样存储 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)
这两个是一样的
\n\nMyClass.objects.prefetch_related(\'relation\')\n\nMyClass.objects.prefetch_related(\n Prefetch(\'relation\', to_attr=\'relation_as_list\')\n)\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n您可以使用 Prefetch 对象进一步控制预取操作(文档)
\n
Prefetch仅当您需要细化 的结果时才需要对象prefetch_related。例如,您可能不需要除relation特定之外的所有查询,因此您可以优化预取查询。
\n\n\n在过滤预取结果时,建议使用 to_attr,因为它比将过滤结果存储在相关 manager\xe2\x80\x99s 缓存中更明确(文档)
\n
to_attr不会带来额外的性能提升,它允许使Prefetch关系不那么模糊,并且可以使用不同的查询集预取相同的关系。
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)\nRun Code Online (Sandbox Code Playgroud)\n\n如果您预取与不同Prefetch对象的相同关系,则每个对象都会有一个额外的查询。生成的预取查询集将存储在列表中,但结果不是像您假设的那样的列表relation_as_list。它们是查询集。在您的示例中,可以使用all(), likemy_obj.relation_as_list.all()和来访问这两个关系my_obj.relation.all()
关于性能提升
\n\n总之,prefetch_related在一次(额外的)数据库命中中获取相关对象,这就是性能提升的来源。Prefetch对象可让您进一步细化此数据库调用。
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) \nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4716 次 |
| 最近记录: |