Django の QuerySet を効果的に使用する

巴扎黑
リリース: 2017-04-05 15:05:57
オリジナル
1937 人が閲覧しました

オブジェクト リレーショナル マッピング (ORM) を使用すると、SQL データベースとの対話が簡単になりますが、非効率的で生の SQL よりも遅いとも考えられています。

ORM を効果的に使用するには、ORM がデータベースにクエリを実行する方法を理解する必要があります。この記事では、Django ORM システムを効果的に使用して中規模から大規模のデータ セットにアクセスする方法に焦点を当てます。

Django のクエリセットは怠惰です

Django のクエリセットは、オプションのクエリでフィルタリングされた、データベース内の複数のレコード (行) に対応します。たとえば、次のコードはデータベース内の「Dave」という名前のすべての人物を取得します:

person_set = Person.objects.filter(first_name="Dave")
ログイン後にコピー

上記のコードはデータベース クエリを実行しません。 person_set を使用したり、フィルタ条件を追加したり、関数に渡したりすることができます。これらの操作はデータベースに送信されません。データベース クエリは Web アプリケーションのパフォーマンスに大きな影響を与える要素の 1 つであるため、これは正しいことです。

実際にデータベースからデータを取得するには、queryset:

for person in person_set:
    print(person.last_name)
ログイン後にコピー

を走査する必要があります。 Django のクエリセットにはキャッシュがあります

クエリセットを反復処理すると、一致するすべてのレコードがデータベースから取得され、Django モデルに変換されます。これを評価といいます。これらのモデルはクエリセットの組み込みキャッシュに保存されるため、クエリセットを再度反復処理する場合に、同じ一般的なクエリを再度実行する必要はありません。

たとえば、次のコードはデータベース クエリのみを実行します:

pet_set = Pet.objects.filter(species="Dog")
# The query is executed and cached.
for pet in pet_set:
    print(pet.first_name)
# The cache is used for subsequent iteration.
for pet in pet_set:
    print(pet.last_name)
ログイン後にコピー

if ステートメントはクエリセットの実行をトリガーします

クエリセット キャッシュの最も便利な点は、クエリセットにデータが含まれているかどうかを効果的にテストできることです。データが存在する場合にのみスキャンされます。 すべてのデータが必要ない場合は、クエリセットのキャッシュに問題がある可能性があります

場合によっては、すべてのデータを走査せずに、データが存在するかどうかだけを知りたい場合があります。この場合、if ステートメントを使用して判断するだけで、データは必要ありませんが、クエリセット全体が完全に実行され、データがキャッシュに入れられます。

りー

これを回避するには、exists() メソッドを使用してデータがあるかどうかを確認できます:

restaurant_set = Restaurant.objects.filter(cuisine="Indian")
# `if`语句会触发queryset的执行。
if restaurant_set:
    # 遍历时用的是cache中的数据
    for restaurant in restaurant_set:
        print(restaurant.name)
ログイン後にコピー

クエリセットが非常に大きい場合、キャッシュが問題になります

数千のレコードを処理する場合、それらを一度にメモリにロードするのは無駄です。さらに悪いことに、巨大なクエリセットによってシステム プロセスがロックされ、プログラムがクラッシュ寸前に陥る可能性があります。

データの走査中にクエリセット キャッシュが生成されないようにするには、 iterator() メソッドを使用してデータを取得し、データの処理後にそれを破棄します。

りー

もちろん、キャッシュの生成を防ぐために iterator() メソッドを使用すると、同じクエリセットを走査するときにクエリが繰り返し実行されることになります。したがって、 iterator() を使用するときは注意し、大規模なクエリセットを操作するときにコードがクエリを繰り返し実行しないようにしてください

クエリセットが大きい場合、if ステートメントが問題になります

前述したように、クエリセット キャッシュは if ステートメントと for ステートメントを組み合わせるのに強力であり、クエリセットでの条件付きループが可能になります。ただし、非常に大規模なクエリ セットの場合、クエリ セットのキャッシュは適していません。

最も簡単な解決策は、exists() を iterator() と組み合わせて使用​​し、2 つのデータベース クエリを使用してクエリセット キャッシュの使用を回避することです。

りー

より複雑な解決策は、Python の「高度な反復メソッド」を使用して、ループを開始する前に iterator() の最初の要素を調べてから、ループするかどうかを決定することです。

りー

不適切な最適化を防ぐ

クエリセットのキャッシュは、データベースに対するプログラムのクエリを減らすために使用され、通常の使用では、必要な場合にのみデータベースがクエリされるようになります。

プログラムのメモリ使用を最適化するには、exists() メソッドと iterator() メソッドを使用します。ただし、クエリセット キャッシュは生成されないため、追加のデータベース クエリが発生する可能性があります。

したがって、プログラムの速度が低下し始めた場合は、コードのどこにボトルネックがあるのか​​、役立つ小さな最適化があるかどうかを確認する必要があります。

以上がDjango の QuerySet を効果的に使用するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート