1. ホーム
  2. パイソン

[解決済み】Django ORMのselect_relatedとprefetch_relatedの違いは何ですか?

2022-03-24 22:04:07

質問

Djangoのドキュメントで。

select_related() クエリを実行する際に、外部キーの関係に従って、関連オブジェクトのデータを追加で選択します。

prefetch_related() はそれぞれの関係に対して個別の検索を行い、Pythonで"join"を行います。

pythonで結合を行うとはどういう意味ですか?どなたか例を挙げて説明していただけませんか?

私の理解では、外部キーリレーションには select_related で、M2Mリレーションシップの場合は prefetch_related . これは正しいのでしょうか?

解決方法は?

あなたの理解はほぼ正しいです。あなたは select_related は、選択するオブジェクトが1つである場合なので OneToOneField または ForeignKey . あなたは prefetch_related を取得する場合は、quot;set" を取得することになります。 ManyToManyField は、あなたが述べたように、あるいは逆に ForeignKey s. 私が言いたいのは、「逆」です。 ForeignKey s"の例です。

class ModelA(models.Model):
    pass

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

ModelB.objects.select_related('a').all() # Forward ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all() # Reverse ForeignKey relationship

という違いがあります。 select_related は SQL ジョインを行い、その結果を SQL サーバーからテーブルの一部として取得します。 prefetch_related 一方、別のクエリを実行することで、元のオブジェクトの冗長なカラムを減らすことができます ( ModelA を使用します(上の例)。を使うことができます。 prefetch_related を使うことができるものであれば、何でも select_related を使用します。

トレードオフは prefetch_related は、選択する ID のリストを作成してサーバーに送信する必要があり、これには時間がかかります。これをトランザクションで行う良い方法があるかどうかは分かりませんが、私の理解では、 Django は常にリストを送信して SELECT ... WHERE pk IN (...,..,..) と言うだけだと思います。この場合、プリフェッチされたデータがまばらであれば (例えば U.S. State オブジェクトが人々の住所にリンクされているとしましょう)、これは非常に良いことですが、1対1に近い場合は、これは多くの通信を浪費する可能性があります。もし疑問があれば、両方を試してみて、どちらがより良いパフォーマンスをするか見てみてください。

上記で述べたことは、基本的にデータベースとの通信に関することです。しかし、Python側では prefetch_related には、データベース内の各オブジェクトを1つのオブジェクトで表すことができるという利点があります。これは select_related Python では、それぞれの "parent"オブジェクトに対して、重複したオブジェクトが作成されます。Pythonのオブジェクトはそれなりにメモリのオーバーヘッドを持つので、これも考慮すべき点です。