Django ORM 中的 select_related 和 prefetch_related 有什么区别?

2025-01-17 09:22:00
admin
原创
14
摘要:问题描述:在 Django 文档中:select_related()“遵循”外键关系,在执行查询时选择额外的相关对象数据。prefetch_related()对每个关系进行单独查找,并在 Python 中执行“连接”。“在 Python 中进行连接”是什么意思?有人可以举例说明吗?我的理解是,对于外键关系,使...

问题描述:

在 Django 文档中:

select_related()“遵循”外键关系,在执行查询时选择额外的相关对象数据。

prefetch_related()对每个关系进行单独查找,并在 Python 中执行“连接”。

“在 Python 中进行连接”是什么意思?有人可以举例说明吗?

我的理解是,对于外键关系,使用select_related;对于 M2M 关系,使用prefetch_related。这样对吗?


解决方案 1:

你的理解基本正确:

  • select_related:当你要选择的对象是单个对象时,OneToOneField或者ForeignKey

  • prefetch_related:当你要得到一“组”东西时,所以ManyToManyField如你所述或反向ForeignKey

为了澄清我所说的反向的意思ForeignKey,这里有一个例子:

class ModelA(models.Model):
    pass

class ModelB(models.Model):
    a = ForeignKey(ModelA)

# Forward ForeignKey relationship
ModelB.objects.select_related('a').all()

# Reverse ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all() 

不同之处在于:

  • select_related执行 SQL 连接,然后从 SQL 服务器获取表的一部分作为结果

  • prefetch_related另一方面执行另一个查询,从而减少原始对象中的冗余列(ModelA在上面的例子中)

你可以用它prefetch_related来做任何你能做select_related的事情。

权衡是prefetch_related必须创建并发送 ID 列表以选择回服务器,这可能需要一段时间。我不确定是否有一个好的方法可以在事务中完成此操作,但我的理解是 Django 总是只发送一个列表并说 SELECT ... WHERE pk IN (...,...,...) 基本上。在这种情况下,如果预取的数据是稀疏的(比如说链接到人们地址的美国州对象),这可能非常好,但是如果它更接近一对一,这可能会浪费大量通信。如果有疑问,请尝试两者并查看哪个性能更好。

上面讨论的所有内容基本上都是关于与数据库的通信。然而,在 Python 方面,prefetch_related还有一个额外的好处,那就是使用单个对象来表示数据库中的每个对象。select_related对于每个“父”对象,Python 中将创建重复的对象。由于 Python 中的对象有相当大的内存开销,因此这也可以作为一个考虑因素。

解决方案 2:

浏览了已经发布的答案。只是觉得如果我添加一个带有实际示例的答案会更好。

假设您有 3 个相关的 Django 模型。

class M1(models.Model):
    name = models.CharField(max_length=10)

class M2(models.Model):
    name = models.CharField(max_length=10)
    select_relation = models.ForeignKey(M1, on_delete=models.CASCADE)
    prefetch_relation = models.ManyToManyField(to='M3')

class M3(models.Model):
    name = models.CharField(max_length=10)

在这里您可以使用字段查询M2模型及其相关M1对象,也可以使用字段查询对象。select_relation`M3`prefetch_relation

但是,正如我们提到M1的那样M2ForeignKey它只为任何对象返回1 条M2记录。同样的事情OneToOneField也适用于。

但是M3的关系M2ManyToManyField可能返回任意数量的M1对象。

假设您有 2 个M2对象m21m22它们有5 个M3相同的ID 关联对象。当您为每个对象1,2,3,4,5获取关联对象时,如果您使用 select related,它的工作方式如下。M3`M2`

步骤:

  1. 尋找m21對象。

  2. 查询与ID 为 的对象M3相关的所有对象。m21`1,2,3,4,5`

  3. m22对对象和所有其他对象重复相同的操作M2

1,2,3,4,5由于两个对象具有相同的 ID m21,如果m22我们使用 select_related 选项,它将两次查询数据库以获取已经获取的相同 ID。

相反,如果您使用 prefetch_related,当您尝试获取M2对象时,它将在查询表时记录您的对象返回的所有 ID(注意:仅 ID)M2,作为最后一步,Django 将使用M3您的对象返回的所有 ID 的集合对表进行查询M2。并M2使用 Python 而不是数据库将它们连接到对象。

这样,您只需查询所有M3对象一次,从而提高性能,因为 python 连接比数据库连接更便宜。

解决方案 3:

两种方法都达到了相同的目的,即放弃不必要的数据库查询。但它们使用不同的方法来提高效率。

使用这两种方法的唯一原因是,单个大型查询比多个小型查询更可取。Django 使用大型查询预先在内存中创建模型,而不是对数据库执行按需查询。

select_related每次查找时执行连接,但扩展选择以包含所有连接表的列。但是这种方法有一个警告。

连接可能会使查询中的行数增加几倍。当您通过外键或一对一字段执行连接时,行数不会增加。但是,多对多连接没有这种保证。因此,Django 限制了不会select_related意外导致大量连接的关系。

“python 中的 join”比它prefetch_related应该的要令人担忧一些。它为每个要连接的表创建一个单独的查询。它使用 WHERE IN 子句过滤每个表,例如:

SELECT "credential"."id",
       "credential"."uuid",
       "credential"."identity_id"
FROM   "credential"
WHERE  "credential"."identity_id" IN
    (84706, 48746, 871441, 84713, 76492, 84621, 51472);

不是执行可能包含过多行的单个连接,而是将每个表拆分为单独的查询。

解决方案 4:

选择相关():
  • 可以将一对一关系中正向外键反向外键的多个SELECT查询减少为仅 1 个查询,也可以将一对多和多对多关系中正向外键的SELECT查询减少为仅 1 个查询。

  • 不能在一对多和多对多关系中与反向外键一起使用。

prefetch_related():
  • 在一对一、一对多和多对多关系中,可以使用前向外键反向外键SELECT将多个查询减少到SELECT至少 2 个查询。

*您可以看到我的回答,其中解释了前向外键反向外键的含义。

下面展示了我在一对一、一对多和多对多关系中使用正向外键select_related()反向外键的实验。prefetch_related()

<一对一关系>

例如,有PersonPersonDetail具有一对一关系的模型,如下所示:

# "app/models.py

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class PersonDetail(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE)
    age = models.IntegerField()
    gender = models.CharField(max_length=20)

    def __str__(self):
        return str(self.age) + " " + self.gender

并且,有PersonPersonDetail管理员,如下所示:

# "app/admin.py

from django.contrib import admin
from .models import Person, PersonDetail

class PersonDetailInline(admin.TabularInline):
    model = PersonDetail
    
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    inlines = (PersonDetailInline,)
    list_display = ('id', 'name')
    ordering = ('id',)

@admin.register(PersonDetail)
class PersonDetailAdmin(admin.ModelAdmin):
    list_display = ('id', 'age', 'gender', 'person')
    ordering = ('id',)

那么Personadmin就有5个对象,如下所示:

在此处输入图片描述

并且,PersonDetailadmin 有 5 个对象,如下所示:

在此处输入图片描述

<前向外键>

然后,我Person从模型中迭代模型PersonDetail,如下所示:

for obj in PersonDetail.objects.all():
    print(obj.person)

然后控制台上会输出以下内容:

John
David
Lisa
Kai
Anna

然后,SELECT运行 6 个查询,如下所示。 *我使用 PostgreSQL,下面是 PostgreSQL 的查询日志,您可以看到我的回答,其中解释了如何在 PostgreSQL 上启用和禁用查询日志:

在此处输入图片描述

接下来,我用从模型迭代Person模型,如下所示。 *和的顺序无关紧要:PersonDetail`select_related("person")select_related()all()`

for obj in PersonDetail.objects.select_related("person").all():
    print(obj.person)

然后控制台上会输出以下内容:

John
David
Lisa
Kai
Anna

然后,SELECT运行 1 个查询,如下所示:

在此处输入图片描述

接下来,我用从模型迭代Person模型,如下所示。 *和的顺序无关紧要:PersonDetail`prefetch_related("person")prefetch_related()all()`

for obj in PersonDetail.objects.prefetch_related("person").all():
    print(obj.person)

然后控制台上会输出以下内容:

John
David
Lisa
Kai
Anna

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<反向外键>

接下来,我PersonDetail从模型中迭代模型Person,如下所示:

for obj in Person.objects.all():
    print(obj.persondetail)

然后控制台上会输出以下内容:

32 Male
18 Male
26 Female
36 Male
21 Female

然后SELECT运行 ​​6 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代PersonDetail模型,如下所示:Person`select_related("persondetail")`

for obj in Person.objects.select_related("persondetail").all():
    print(obj.persondetail)

然后控制台上会输出以下内容:

32 Male
18 Male
26 Female
36 Male
21 Female

然后,SELECT运行 1 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代PersonDetail模型,如下所示:Person`prefetch_related("persondetail")`

for obj in Person.objects.prefetch_related("persondetail").all():
    print(obj.persondetail)

然后控制台上会输出以下内容:

32 Male
18 Male
26 Female
36 Male
21 Female

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<一对多关系>

例如,有CategoryProduct具有一对多关系的模型,如下所示:

# "app/models.py"

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class Product(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    price = models.DecimalField(decimal_places=2, max_digits=5)

    def __str__(self):
        return str(self.category) + " " + self.name + " " + str(self.price)

并且,有CategoryProduct管理员,如下所示:

# "app/admin.py"

from django.contrib import admin
from .models import Category, Product
    
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ('id', 'name')
    ordering = ('id',)

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'price', 'category')
    ordering = ('id',)

那么Categoryadmin就有4个对象,如下所示:

在此处输入图片描述

并且,Productadmin 有 6 个对象,如下所示:

在此处输入图片描述

<前向外键>

然后,我Category从模型中迭代模型Product,如下所示:

for obj in Product.objects.all():
    print(obj.category)

然后控制台上会输出以下内容:

Fruits
Fruits
Vegetable
Meat
Meat
Fish

然后SELECT运行 ​​7 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Category模型,如下所示:Product`select_related("category")`

for obj in Product.objects.select_related("category").all():
    print(obj.category)

然后控制台上会输出以下内容:

Fruits
Fruits
Vegetable
Meat
Meat
Fish

然后,SELECT运行 1 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Category模型,如下所示:Product`prefetch_related("category")`

for obj in Product.objects.prefetch_related("category").all():
    print(obj.category)

然后控制台上会输出以下内容:

Fruits
Fruits
Vegetable
Meat
Meat
Fish

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<反向外键>

接下来,我Product从模型中迭代模型Category,如下所示:

for obj in Category.objects.all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Fruits Apple 10.00>, <Product: Fruits Orange 20.00>]>
<QuerySet [<Product: Vegetable Carrot 30.00>]>
<QuerySet [<Product: Meat Chicken 40.00>, <Product: Meat Beef 50.00>]>
<QuerySet [<Product: Fish Salmon 60.00>]>

然后SELECT运行 ​​5 个查询,如下所示:

在此处输入图片描述

接下来,我尝试从模型中迭代Product模型,如下所示:Category`select_related("product_set")`

for obj in Category.objects.select_related("product_set").all():
    print(obj.product_set.all())

然后,由于不能与反向外键select_related("product_set")一起使用,会出现以下错误:

django.core.exceptions.FieldError: select_related 中给出的字段名称无效:'product_set'。选项有:(无)

实际上,如果我不使用参数select_related()则不会出现错误,如下所示:

                                        # ↓ No argument
for obj in Category.objects.select_related().all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Fruits Apple 10.00>, <Product: Fruits Orange 20.00>]>
<QuerySet [<Product: Vegetable Carrot 30.00>]>
<QuerySet [<Product: Meat Chicken 40.00>, <Product: Meat Beef 50.00>]>
<QuerySet [<Product: Fish Salmon 60.00>]>

但是,SELECT仍然运行 5 个查询而不是 1 个SELECT查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Product模型,如下所示:Category`prefetch_related("product_set")`

for obj in Category.objects.prefetch_related("product_set").all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Fruits Apple 10.00>, <Product: Fruits Orange 20.00>]>
<QuerySet [<Product: Vegetable Carrot 30.00>]>
<QuerySet [<Product: Meat Chicken 40.00>, <Product: Meat Beef 50.00>]>
<QuerySet [<Product: Fish Salmon 60.00>]>

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<多对多关系>

例如,CategoryProduct模型具有多对多关系,如下所示:

# "app/models.py"

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class Product(models.Model):
    categories = models.ManyToManyField(Category)
    name = models.CharField(max_length=50)
    price = models.DecimalField(decimal_places=2, max_digits=5)
    
    def __str__(self):
        return self.name + " " + str(self.price)

并且,有CategoryProduct管理员,如下所示:

# "app/admin.py

from django.contrib import admin
from .models import Category, Product
    
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'get_products')
    ordering = ('id',)

    @admin.display(description='products')
    def get_products(self, obj):
        return [product.name for product in obj.product_set.all()]

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'price', 'get_categories')
    ordering = ('id',)

    @admin.display(description='categories')
    def get_categories(self, obj):
        return [category.name for category in obj.categories.all()]

那么Categoryadmin就有5个对象,如下所示:

在此处输入图片描述

并且,Productadmin 有 6 个对象,如下所示:

在此处输入图片描述

<前向外键>

然后,我Category从模型中迭代模型Product,如下所示:

for obj in Product.objects.all():
    print(obj.categories.all())

然后控制台上会输出以下内容:

<QuerySet [<Category: Fruits>, <Category: 20% OFF>]>
<QuerySet [<Category: Fruits>]>
<QuerySet [<Category: Vegetable>]>
<QuerySet [<Category: Meat>, <Category: 20% OFF>]>
<QuerySet [<Category: Meat>]>
<QuerySet [<Category: Fish>, <Category: 20% OFF>]>

然后SELECT运行 ​​7 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Category模型,如下所示:Product`select_related("categories")`

for obj in Product.objects.select_related("categories").all():
    print(obj.categories.all())

然后,由于不能与反向外键select_related("categories")一起使用,会出现以下错误:

django.core.exceptions.FieldError: select_related 中给出的字段名称无效:'categories'。选项有:(无)

实际上,如果我不使用参数select_related()则不会出现错误,如下所示:

                                       # ↓ No argument
for obj in Product.objects.select_related().all():
    print(obj.categories.all())

然后控制台上会输出以下内容:

<QuerySet [<Category: Fruits>, <Category: 20% OFF>]>
<QuerySet [<Category: Fruits>]>
<QuerySet [<Category: Vegetable>]>
<QuerySet [<Category: Meat>, <Category: 20% OFF>]>
<QuerySet [<Category: Meat>]>
<QuerySet [<Category: Fish>, <Category: 20% OFF>]>

但是,SELECT仍然运行了 7 个查询,而不是 1 个SELECT查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Category模型,如下所示:Product`prefetch_related("categories")`

for obj in Product.objects.prefetch_related("categories").all():
    print(obj.categories.all())

然后控制台上会输出以下内容:

<QuerySet [<Category: Fruits>, <Category: 20% OFF>]>
<QuerySet [<Category: Fruits>]>
<QuerySet [<Category: Vegetable>]>
<QuerySet [<Category: Meat>, <Category: 20% OFF>]>
<QuerySet [<Category: Meat>]>
<QuerySet [<Category: Fish>, <Category: 20% OFF>]>

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<反向外键>

接下来,我Product从模型中迭代模型Category,如下所示:

for obj in Category.objects.all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Apple 10.00>, <Product: Orange 20.00>]>
<QuerySet [<Product: Carrot 30.00>]>
<QuerySet [<Product: Chicken 40.00>, <Product: Beef 50.00>]>
<QuerySet [<Product: Salmon 60.00>]>
<QuerySet [<Product: Apple 10.00>, <Product: Chicken 40.00>, <Product: Salmon 60.00>]>

然后SELECT运行 ​​6 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Product模型,如下所示:Category`select_related("product_set")`

for obj in Category.objects.select_related("product_set").all():
    print(obj.product_set.all())

然后,由于不能与反向外键select_related("categories")一起使用,会出现以下错误:

django.core.exceptions.FieldError: select_related 中给出的字段名称无效:'product_set'。选项有:(无)

实际上,如果我不使用参数select_related()则不会出现错误,如下所示:

                                        # ↓ No argument
for obj in Category.objects.select_related().all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Apple 10.00>, <Product: Orange 20.00>]>
<QuerySet [<Product: Carrot 30.00>]>
<QuerySet [<Product: Chicken 40.00>, <Product: Beef 50.00>]>
<QuerySet [<Product: Salmon 60.00>]>
<QuerySet [<Product: Apple 10.00>, <Product: Chicken 40.00>, <Product: Salmon 60.00>]>

但是,SELECT仍然运行了 6 个查询,而不是 1 个SELECT查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Product模型,如下所示:Category`prefetch_related("product_set")`

for obj in Category.objects.prefetch_related("product_set").all():
    print(obj.product_set.all())

然后控制台上会输出以下内容:

<QuerySet [<Product: Apple 10.00>, <Product: Orange 20.00>]>
<QuerySet [<Product: Carrot 30.00>]>
<QuerySet [<Product: Chicken 40.00>, <Product: Beef 50.00>]>
<QuerySet [<Product: Salmon 60.00>]>
<QuerySet [<Product: Apple 10.00>, <Product: Chicken 40.00>, <Product: Salmon 60.00>]>

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

<附加实验>

例如,有CountryStateCity模型具有一对多关系,如下所示:

# "app/models.py"

from django.db import models

class Country(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class State(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name
    
class City(models.Model):
    state = models.ForeignKey(State, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

其中,有CountryStateCity管理员,如下所示:

# "app/admin.py

from django.contrib import admin
from .models import Country, State, City
    
@admin.register(Country)
class CountryAdmin(admin.ModelAdmin):
    list_display = ('id', 'name')
    ordering = ('id',)

@admin.register(State)
class StateAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'get_country')
    ordering = ('id',)

    @admin.display(description='country')
    def get_country(self, obj):
        return obj.country

@admin.register(City)
class CityAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'get_state', 'get_country')
    ordering = ('id',)

    @admin.display(description='state')
    def get_state(self, obj):
        print(obj)
        return obj.state

    @admin.display(description='country')
    def get_country(self, obj):
        return obj.state.country

那么Countryadmin有2个对象,如下所示:

在此处输入图片描述

并且,Stateadmin 有 3 个对象,如下所示:

在此处输入图片描述

那么Cityadmin就有6个对象,如下所示:

在此处输入图片描述

<前向外键>

然后,我使用模型迭代Country模型,如下所示:City`select_related("state__country")`

for obj in City.objects.all().select_related("state__country"):
    print(obj.state.country)

然后控制台上会输出以下内容:

USA
USA
USA
USA
Japan
Japan

然后,SELECT运行 1 个查询,如下所示:

在此处输入图片描述

接下来,我使用模型迭代Country模型,如下所示:City`prefetch_related("state__country")`

for obj in City.objects.all().prefetch_related("state__country"):
    print(obj.state.country)

然后控制台上会输出以下内容:

USA
USA
USA
USA
Japan
Japan

然后SELECT运行 ​​3 个查询,如下所示:

在此处输入图片描述

<反向外键>

接下来,我使用模型迭代City模型,如下所示:Country`prefetch_related("state_set__city_set")`

for country_obj in Country.objects.all().prefetch_related("state_set__city_set"):
    for state_obj in country_obj.state_set.all():
        for city_obj in state_obj.city_set.all():
            print(city_obj)

然后控制台上会输出以下内容:

San Francisco
Los Angeles
San Diego
Kansas City
Ginza
Akihabara

然后SELECT运行 ​​3 个查询,如下所示:

在此处输入图片描述

接下来,我使用filter()而不是all()从模型中迭代City模型,如下所示。* with不起作用:Country`prefetch_related("state_set__city_set")prefetch_related()filter()`

                                  # Here
for country_obj in Country.objects.filter().prefetch_related("state_set__city_set"):
    for state_obj in country_obj.state_set.filter(): # Here
        for city_obj in state_obj.city_set.filter(): # Here
            print(city_obj)

然后控制台上会输出以下内容:

San Francisco
Los Angeles
San Diego
Kansas City
Ginza
Akihabara

然后SELECT运行 ​​8 个查询,如下所示:

在此处输入图片描述

因此,为了减少 8 个SELECT查询,我需要使用Prefetch(),filter()但我只知道如何使用和从模型迭代State模型,如下所示。 *我在 Stack Overflow 上询问了如何使用和从模型迭代模型的问题:Country`Prefetch()filter()CityCountryPrefetch()`filter()

for country_obj in Country.objects.filter().prefetch_related(
    Prefetch('state_set', # Here
        queryset=State.objects.filter(),
        to_attr='state_obj'
    )
):
    print(country_obj.state_obj)

然后控制台上会输出以下内容:

[<State: California>, <State: Missouri>]
[<State: Tokyo>]

然后SELECT运行 ​​2 个查询,如下所示:

在此处输入图片描述

解决方案 5:

不要混淆

select_related:用于ForeignKey关系,

prefetch_related:用于ManyToManyField关系或反向ForeignKey。

它们做同样的事情,减少查询的数量

例如:

class ExampleClassA(models.Model):
    title = models.CharField(max_length=50)

class ExampleClassB(models.Model):
    example_class_a = models.ForeignKey(ExampleClassA,
        on_delete=models.CASCADE)



objects = ExampleClassB.objects.all() 

for obj in objects:
    print(obj.example_class_a.title) 

查询次数(访问相关字段):N+1(# n 是 ExampleClassA 的对象数量)

如果我们使用此查询:

objects = ExampleClassB.objects.select_related('example_class_a').all()

查询数量只有一个。

解决方案 6:

让我试着向你展示 Django 如何在 select_related 和 prefetch_related 中进行数据库调用

class a(models.Model):
    name = models.CharField(max_length=100)

class b(models.Model):
    name = models.CharField(max_length=100)
    a = models.ForeignKey(A, on_delete=models.CASCADE)

select_related 查询->

b.objects.select_related('a').first()

为此执行的 SQL 查询将是

SELECT * FROM "b" LEFT OUTER JOIN "a" ON ("b"."a_id" = "a"."id") LIMIT 1

这里 Django 将使用 JOIN 获取“a”模型的详细信息

prefetch_related 查询->

B.objects.prefetch_related('a').first()

为此执行的 SQL 查询将是

SELECT * FROM "b" LIMIT 1
SELECT * FROM "a" WHERE "a"."id" IN (ids collected from above query)

这里Django将执行两个SQL查询并通过python合并它们

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1043  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   41  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   35  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   32  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   34  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用