表のデータ:
from django.db import models
class Province(models.Model):
name = models.CharField(max_length=10)
def __str__(self):
return self.name
class City(models.Model):
name = models.CharField(max_length=5)
province = models.ForeignKey(Province)
def __str__(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 __str__(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)
上記のSQL文の実装では、複数のクエリを引き起こし
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`
WHERE `QSOptimize_province`.`id` = 1 ;
使用して、select_related:
citys = City.objects.select_related().all()
for c in citys:
print (c.province)
SQLクエリは一度だけ、大幅に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`) ;
DjangoはINNER JOINを要求を満たすために使用されます
多くの外部キークエリ
可変長パラメータは()受け付けるselect_related、各パラメータは、外部キーを取得する必要があるフィールド名、フィールド名と外部キー外部キー、外部キー外部キー外部キー.... 外部キー外部キーを選択するには、接続するために2つのアンダースコア「_」を使用する必要があります。
注意:指定なし外部キーが結果に追加されません
1.7前
zhangs=Person.objects.select_related('hometown__province','living__province')
.get(firstname="张",lastname="三")
zhangs.hometown.province
zhangs.living.province
連鎖の1.7をサポートした後、
zhangs=Person.objects.select_related('hometown__province')
.select_related('living__province').get(firstname="张",lastname="三")
zhangs.hometown.province
zhangs.living.province
深照会深さ
Djangoは再帰的深さで指定したすべてのOneToOneFieldとのForeignKeyを横断します。この例で示しています。
zhangs = Person.objects.select_related(depth = d)
# d=1 相当于 select_related('hometown','living')
# d=2 相当于 select_related('hometown__province','living__province')
引数はありません
これは)(select_relatedできるだけ深いジャンゴを要求したことを示しています
注意:Djangoはあなたがどのようなフィールドの実際の使用がわからないので、すべてのフィールドがでキャッチされますが、不要な廃棄物が発生し、パフォーマンスに影響を与えるであろう
要約:
- そして、メインニードルの最適化の間に多対1の関係
- SQLを使用すると、ステートメントJOINの最適化は、SQLクエリの数を削減し、パフォーマンスを向上させることにより、最適化されます。
- 可変長パラメータが必要select_relatedフィールド名を指定します。また、使用することができ、二重のアンダースコアを指定したフィールド名再帰クエリを達成するための接続「__」。
- 指定しないフィールドがキャッシュされないことはありません、指定されていない深さは、アクセスしたい場合は、Djangoは再びSQLクエリを行います、キャッシュされません。
- Djangoが自動的に指定された深さの範囲内のすべてのフィールドをキャッシュし、再帰の深さパラメータの深さによって指定することができます。あなたは深さの指定したフィールドの外にアクセスしたい場合は、Djangoは再びSQLクエリを行います。
- 引数は呼び出しません受け入れ、Djangoはすべてのフィールドに深い再帰クエリをしようとします。しかし、廃棄物があることに注意してDjangoの再帰の性能を制限。
- Djangoは> = 1.7、連鎖呼び出しが可変長のパラメータを使用するのと同じselect_related。ジャンゴ<1.7、チェーンのコールは最後のものだけを残して、失敗select_relatedフロントにつながります。
二、prefetch_related
多くの分野(のManyToManyField)と多くの分野に多くの場合、あなたは、最適化する)(prefetch_related使用することができます。おそらく、あなたは、OneToManyField事ああと呼ばれる誰も言わないだろう。実際には、ForeignKeyのは、多対フィールドですが、フィールドがForeignKeyのは、フィールドの多くに関連していますさ。
prefetch_related()とselect_related()SQLクエリの数ではなく、達成するのと同じ方法を削減することです。後者はによってれるJOINの SQLクエリで問題を解決するために、ステートメントを。しかし、多くの関係のために、テーブルの使用が非常に長くなり、SQL文を取得するには、JOIN、それは増加したメモリフットプリントにつながるとSQL文の実行時間が増加します。prefetch_related()溶液を、ある、それぞれのテーブルのクエリ、そして次にPythonでそれらの間の関係に対処
zhangs = Person.objects.prefetch_related('visitation').get(firstname="张",lastname="三")
for city in zhangs.visitation.all() :
print(city)
プリフェッチオブジェクト
- プリフェッチ・オブジェクトは、プリフェッチ動作を割り当てることができます。
- プリフェッチは、フィールド名が接続されている二重下線で行われ、prefetch_relatedフィールドはやり方と同じパラメータを指定するオブジェクト。
- クエリセット・プリフェッチは、手動でクエリセットのパラメータを使用して指定することができます。
あなたはto_attrパラメータでプリフェッチ属性名を指定することができます。- プリフェッチオブジェクトと検索文字列を指定したパラメータを混在させることができます。
要約:
- メインピン対多およびprefetch_related多くを-との関係を最適化します。
- 各テーブルの内容を取得し、その後のPythonとを介してそれらの間の関係を最適化するために、それぞれprefetch_related。
- あなたは、フィールド名は、可変長パラメータによってselect_related必要指定することができます。Select_relatedターゲティングと機能は同じです。
- Djangoのでは> = 1.7は、複雑なクエリプリフェッチオブジェクトを介して達成することができます。
- prefetch_relatedパラメータとして、プリフェッチ・オブジェクトと文字列を混合することができます。
- prefetch_related鎖は、異なるバージョンに基づいて区別が存在しないと思われ、対応するプリフェッチがなく置き換えるよりも、それに加え呼びます。
- Noneを渡すことでprefetch_related前に空にすることができます。
参考:https://blog.csdn.net/cugbabybear/article/details/38342793