Django ドキュメント:
select_related()
外部キー関係に従い、クエリを実行するときに追加の関連オブジェクト データを選択します。
prefetch_related()
各関係を個別に検索し、Python で「結合」を実行します。
「Python で結合を行う」とはどういう意味ですか? 誰か例を挙げて説明してもらえますか?
私の理解では、外部キー関係の場合は を使用しselect_related
、M2M 関係の場合は を使用しますprefetch_related
。これは正しいですか?
ベストアンサー1
あなたの理解はほぼ正しいです:
select_related
: 選択するオブジェクトが単一のオブジェクトである場合、OneToOneField
またはForeignKey
prefetch_related
: 物事の「セット」を取得する場合は、ManyToManyField
あなたが述べたとおりの s または逆のForeignKey
s を使用します。
逆 s の意味を明確にするために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 (...,...,...) と指定します。この場合、プリフェッチされたデータがまばらであれば (たとえば、人々の住所にリンクされた米国の州オブジェクト)、これは非常に有効ですが、1 対 1 に近い場合は、大量の通信が無駄になる可能性があります。疑問がある場合は、両方を試して、どちらがパフォーマンスが良いかを確認してください。
上で説明した内容は、基本的にデータベースとの通信に関するものです。ただし、Python 側には、prefetch_related
データベース内の各オブジェクトを表すために単一のオブジェクトが使用されるという追加の利点があります。Pythonselect_related
では、各「親」オブジェクトに対して重複したオブジェクトが作成されます。Python のオブジェクトにはかなりのメモリ オーバーヘッドがあるため、これも考慮する必要があります。