DjangoのORM select_related和prefetch_related

データベース内の外部キーselect_related()とprefetch_related使用()よく、それにより性能を向上させる、データベース要求の数を減らすことができます。

一例では、両方の用法、記載:

from django.db import models
 
class Province(models.Model):
    name = models.CharField(max_length=10)
    def __unicode__(self):
        return self.name
 
class City(models.Model):
    name = models.CharField(max_length=5)
    province = models.ForeignKey(Province)
    def __unicode__(self):
        return self.name
 
class Person(models.Model):
    firstname  = models.CharField(max_length=10)
    lastname   = models.CharField(max_length=10)
    visitation = models.ManyToManyField(City, related_name = "visitor")
    hometown   = models.ForeignKey(City, related_name = "birth")
    living     = models.ForeignKey(City, related_name = "citizen")
    def __unicode__(self):
        return self.firstname + self.lastname

select_related:
1フィールド(OneToOneField)および外部キーフィールド(ForeignKeyの)、select_relatedクエリセットを最適化するために使用されてもよいです。Select_relatedクエリセット()関数を使用した後、Djangoはもはやデータベースクエリの後に、必要なときにそのことを、オブジェクトに対応する対応する外部キーを取得しないこと。

私たちはすべての都市と地方とそれぞれのデータベースを印刷する必要がある場合は、最も直接的なアプローチは次のとおりです。

>>> citys = City.objects.all()
>>> for c in citys:
...   print c.province

オブジェクトの数がn個あまり、各オブジェクトが外部キーフィールドkを持って、それがn *のk + 1回のSQLクエリにつながる場合、これは、線形SQLクエリになります。この場合、3つのオブジェクトがあるので、市内に4回、SQLクエリをリードしてきました:

SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
FROM `QSOptimize_city`
 
SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name` 
FROM `QSOptimize_province`
WHERE `QSOptimize_province`.`id` = 1 ;
 
SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name` 
FROM `QSOptimize_province`
WHERE `QSOptimize_province`.`id` = 2 ;
 
SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name` 
FROM `QSOptimize_province`

我々は、select_related()関数を使用する場合:

>>> citys = City.objects.select_related().all()
>>> for c in citys:
...   print c.province

唯一の1つのSQLクエリは、明らかに大幅にSQLクエリの数を減らします:

SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, 
`QSOptimize_city`.`province_id`, `QSOptimize_province`.`id`, `QSOptimize_province`.`name` 
FROM`QSOptimize_city` 
INNER JOIN `QSOptimize_province` ON (`QSOptimize_city`.`province_id` = `QSOptimize_province`.`id`) ;

()prefetch_related
最適化するために多くの分野(のManyToManyField)と多くの分野の多くのために、(prefetch_related使用することができます)。おそらく、あなたは言うだろう、誰もOneToManyFieldの事ああと呼ばれていません。実際には、ForeignKeyのは、多対フィールドですが、フィールドがForeignKeyのは、フィールドの多くに関連していますさ。
prefetch_related()とselect_related()、非常に類似した設計されたSQLクエリの数ではなく、達成するのと同じ方法を減らすことです。(前者はinで文です)、後者でJOINステートメント SQLクエリで問題を解決するために、。結果のテーブルは非常に長くなり、JOIN、それは増加メモリフットプリントにつながるとSQL文の実行している時間が長くなりますので、しかし、多くの関係のために、ビット賢明上のアドレスにSQL文を使用します。n個のオブジェクト場合、フィールド多くミ物品に対応する各オブジェクトは、[シグマ結果テーブル(n)はミ行が生成されます。

prefetch_related()この問題を回避するには、個別のテーブルを照会し、その後のPythonとの関係に対処することです私たちは、それができる、湖北省のすべての都市を取得したいです

>>> hb = Province.objects.prefetch_related('city_set').get(name__iexact=u"湖北省")
>>> for city in hb.city_set.all():
...   city.name

トリガSQLクエリ:

SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name` 
FROM `QSOptimize_province` 
WHERE `QSOptimize_province`.`name` LIKE '湖北省' ;

SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id` 
FROM `QSOptimize_city` 
WHERE `QSOptimize_city`.`province_id` IN (1);

私たちは、プリフェッチ達成するためのINステートメントを使用して、見ることができます。

概要:
以来select_related()は常に問題となっている単一のSQLクエリで解決、(しかしprefetch_related)関連する各テーブルのSQLクエリますのでselect_related、()効率が後者よりも通常は高いです。

公開された44元の記事 ウォンの賞賛0 ビュー3921

おすすめ

転載: blog.csdn.net/cpxsxn/article/details/104759607