説明されるDangango ORM:選択されたCount関連とprefetchchen関連
Django ORMでの作業はSQL文を記述せずにデータベースからデータを検索する方法を提供します.しかし、SQL文の代わりにORMを使用すると、パフォーマンス低下が確実になりますが、大部分のCRUDアプリケーションでは、役に立たないデータベースクエリーを減らして、あなたのDjangoアプリケーションをより速くする方法を探しているまで、それは意味がありません.
このモデルの例を挙げましょう.
プロファイルオブジェクトを持っているなら、ユーザを得るデフォルトの方法は何ですか?
からDjango docs ,
基本的には
フェッチする行を書き直しましょう
ユーザーオブジェクトを持つすべてのプロファイルを取得しなければならない場合を調べましょう.
ユーザーモデルにstrメソッドを追加しましょう.
パフォーマンス問題の例
このモデルの例を挙げましょう.
from django.db import models
class User(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50)
すごい!ここに2つのモデルがありますProfile
モデルはForeignKey
-- 一つから多くへUser
モデルは、ユーザーが多くのプロファイルを持つことができることを意味します.プロファイルオブジェクトを持っているなら、ユーザを得るデフォルトの方法は何ですか?
# hit the database
profile = Profile.objects.first()
# hit the database again to get the related User object
user = profile.user
さて、我々はちょうどここで2つの質問をしました.かなり大きな問題ではありませんが、これらの行を最適化し、不要な問い合わせを避ける必要があります.選択
からDjango docs ,
select_related()
外部キー関係を「フォローします」というクエリを返します.これは、単一のより複雑なクエリをもたらすパフォーマンスのブースターですが、その後の外部キー関係の使用はデータベースクエリを必要としません.基本的には
select_related
選択したいオブジェクトが単一のオブジェクトである場合、OneToOneField
またはForeignKey
. フェッチする行を書き直しましょう
user
を持つprofile
オブジェクト.# Hits the database
profile = Profile.objects.select_related('user').first()
# Doesn't hit the database, because profile.user has been prepopulated
# in the previous query.
user = profile.user
そして、我々はちょうど2つの質問を1に変えました.しかし、あなたが持っているとき、何が起こりますかManyToMany
関係ManyToOne
? ユーザーオブジェクトを持つすべてのプロファイルを取得しなければならない場合を調べましょう.
プリフェッチ関連
ユーザーモデルにstrメソッドを追加しましょう.
class User(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
password = models.CharField(max_length=50)
def __str__(self) -> str:
return "%s (%s)" % (self.name,
", ".join(profile.first_name for profile in self.profile_set.all()))
Note: If you are using a
ForeignKey
relationship in Django between an M1 model and an M2 model -- which is symmetrical by default --, the M1 model has automatically a reverse relationship field of typeManyToOne
.
次のコードを実行すると、次の結果が得られます.この質問の問題は、毎回>>> User.objects.all() [<User: User (John Doe)>, <User: User (Jane Doe)> ...]
__str__
ユーザーモデルのメソッドをコールします.self.profile_set.all()
.
そして、クエリの数は、ユーザーによるプロファイルの数に比例しています:よく、悪夢.🥶
しかし、どのように我々はちょうど2つの質問にこれを減らすことができますか?まあ、使用prefetch_related
.使用するUser.objects.prefetch_related('profile_set').all()
prefetch_related
あなたが物事の「セット」を得るつもりであるときManyToMany
または逆ForeignKey
--ManyToOne
.次に、2つの違いは何ですか?
どちらも、データベースからデータをプリフェッチするのと同じ原理で動作しますが、それらは異なるアプローチを行います.
すでに以下に述べましたが、この内容について結論を出しましょう.使用する select_related
選択したいオブジェクトが単一のオブジェクトである場合、OneToOneField
またはForeignKey
.使用する ただし、これらのメソッドを使用する必要があります場合は、データベースのクエリ番号を削減し、データベースからのデータのより大きなサイズを取得する問題はありません.prefetch_related
あなたが物事の「セット」を得るつもりであるときManyToMany
または逆ForeignKey
--ManyToOne
.
私の経験では、これらのメソッドは本当にJjangoで空腹のcronジョブを実行するのに役に立ちました.🤟
Djangoアプリケーションでのデータベースクエリーを少なくするために、他の方法を使用しますか?コメント欄で議論しましょう.
記事投稿bloggu.io . 無料でお試しください.
Reference
この問題について(説明されるDangango ORM:選択されたCount関連とprefetchchen関連), 我々は、より多くの情報をここで見つけました https://dev.to/koladev/django-orm-explained-selectedrelated-and-prefetchrelated-27a7テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol