select_related と prefetch_related の使い方と違い

0. この記事では django-debug-toolbar を使用して効果を示します

(メッセージ数 19) django-debug-toolbar のicon-default.png?t=M7J4インストール

1 はじめに

select_related:

外部キーの関係(注:1対1および1対多の関係のみ)に従って、SQL内部結合操作を含むSELECTステートメントを作成することにより、主オブジェクトと関連オブジェクトの情報が一度に取得されますクエリステートメントを実行するとき。

prefetch_related

多対多フィールドの場合、select_related メソッドを使用することはできません。これは、多対多フィールドで JOIN 操作を実行し、最終的なテーブルが非常に大きくなるのを避けるために行われます。

Django は、この問題を解決する prefect_related メソッドを提供しています。

prefect_related は、多対多の関係フィールドおよび逆外部キー関係 (related_name) に使用できます。

同じ点:

どちらも queryset オブジェクトに作用します

気をつけて:

  • 1 対 1 または 1 対多の外部キーを持つ ForeignKey フィールドに select_related メソッドを使用する

  • 多対多フィールドと逆外部キーの関係については、prefetch_related メソッドを使用します

  • どちらのメソッドも、クエリ対象の関連オブジェクトのフィールド名を指定するために、2 つのアンダースコアをサポートしています。

  • Prefetch メソッドを使用して、追加の条件と属性を prefetch_related メソッドに追加します。

2.使用

水面

from django.db import models


class UserInfo(models.Model):
    username = models.CharField(verbose_name='用户名', max_length=225)

    def __str__(self):
        return self.username


class Tag(models.Model):
    name = models.CharField(verbose_name='标签名称', max_length=225)

    def __str__(self):
        return self.name


class Article(models.Model):
    title = models.CharField(verbose_name='标题', max_length=225)
    content = models.CharField(verbose_name='内容', max_length=225)
    # 外键
    username = models.ForeignKey(verbose_name='用户', to='UserInfo', on_delete=models.DO_NOTHING)
    tag = models.ManyToManyField(verbose_name='标签', to='Tag')

    def __str__(self):
        return self.title

2.1 ネイティブクエリ

2.1.1 コード

def article_list(request):
    if request.method == 'GET':
        # select_related---->queryset
        article_queryset = models.Article.objects.all()
        return render(request, 't2.html', context={'article_queryset': article_queryset})

2.1.2 イラスト

2.1.3 クエリの説明 

1. 図から、合計 13 回のクエリが行われ、10 回の繰り返しがあることがわかります。! !

その理由は: 初めてクエリを実行するとき、返される値は記事オブジェクトのみであり、タグとユーザーのクエリはありません. フロントエンドインターフェースがこれら2つを必要とする場合、各サイクルはデータベースにアクセスしてクエリを実行します.

2. クエリの繰り返しを避けるために、django は select_related および prefetch_related メソッドを提供して、SQL の JOIN メソッドと同様に、データベース クエリの効率を向上させます。

3. 最初のクエリが実行されると、テーブルが接続され、すべてのデータが一度にクエリされます。

2.2 select_related の使用

2.2.2 コード

from django.shortcuts import render

from blog import models


def article_list(request):
    if request.method == 'GET':
        # select_related---->queryset
        article_queryset = models.Article.objects.all().select_related('tag', 'username')
        return render(request, 't2.html', context={'article_queryset': article_queryset})

2.2.3 ダイアグラム

 2.2.4 解釈

現在、クエリは 3 つしかなく、時間が大幅に短縮されていることがわかります。

 2.2.5 その他の一般的な使用法

# 获取id=1的文章对象同时,获取其相关username信息
Article.objects.select_related('username').get(id=1)

# 获取id=1的文章对象同时,获取其相关作者名字信息
Article.objects.select_related('username__username').get(id=1)

# 获取id=1的文章对象同时,获取其相关tag和相关作者名字信息。下面方法等同。
# 方式一:
Article.objects.select_related('tag', 'username__username').get(id=1)
# 方式二:
Article.objects.select_related('tag').select_related('username__username').get(id=1)

# 使用select_related()可返回所有相关主键信息。all()非必需。
Article.objects.all().select_related()

# 获取Article信息同时获取username信息。filter方法和selected_related方法顺序不重要。
# 方式一:
Article.objects.filter(tag__gt=3).select_related('username')
# 方式二:
Article.objects.select_related('username').filter(tag__gt=3)

2.3. prefetch_related メソッドの使用

多対多フィールドの場合、select_related メソッドを使用することはできません。これは、多対多フィールドで JOIN 操作を実行し、最終的なテーブルが非常に大きくなるのを避けるために行われます。

2.3.1 よくあるケース

articles = Article.objects.all().select_related('category').prefecth_related('tags')

# 文章列表及每篇文章的tags对象名字信息
Article.objects.all().prefetch_related('tags__name')

# 获取id=13的文章对象同时,获取其相关tags信息
Article.objects.prefetch_related('tags').get(id=13)

# 获取文章列表及每篇文章相关的名字以P开头的tags对象信息
Article.objects.all().prefetch_related(
    Prefetch('tags', queryset=Tag.objects.filter(name__startswith="P"))
)

# 文章列表及每篇文章的名字以P开头的tags对象信息, 放在article_p_tag列表
Article.objects.all().prefetch_related(
    Prefetch('tags', queryset=Tag.objects.filter(name__startswith="P")),
to_attr='article_p_tag'
)

この記事の参照

Django の基本 (29): select_related と prefetch_related の使用法と違い (qq.com)

https://cn.bing.com/ck/a?!&&p=e0abbfe758bda72aJmltdHM9MTY2MjI0OTYwMCZpZ3VpZD0wZDM2NTliMy1hZDc5LTYwY2YtMDk4Mi00YmI2YWM1NzYxNmMmaW5zaWQ9NTEzNA&ptn=7&hsh=3&fclid=0d3659b3-ad79-60cf-0982-4bb6ac57616c&u=a1aHR0cHM6Ly93d3cuY25ibG9ncy5jb20vY2NvcnovcC82MDk3MTcxLmh0bWw&ntb=1  https://cn.bing.com/ck/a? !&&p=f1ee206eac3dcc27JmltdHM9MTY2MjI0OTYwMCZpZ3VpZD0wZDM2NTliMy1hZDc5LTYwY2YtMDk4Mi00YmI2YWM1NzYxNmMmaW5zaWQ9NTE1Nw&ptn=7&hsh=3&fclid=0d3659b3-ad79-60cf-0982-4bb6ac57616c&u=a1aHR0cHM6Ly93d3cuY25ibG9ncy5jb20vd2FuZ3l1ZTA5MjUvcC8xMTExODczOS5odG1s&ntb=1

おすすめ

転載: blog.csdn.net/qq_52385631/article/details/126695685