3

1つのQuerySetを評価し、次に別のQuerySetを評価していますが、2番目は最初のサブセットです。私はこれを効率的な方法で実行しようとしています。データベースの呼び出しはできるだけ少なくしています。(これは以前に尋ねられましたが、正直に言って、私は答えを完全に理解していませんでした、そしてそれらが私が考えていることに完全に当てはまるかどうかはわかりません。)

Djangoドキュメントのサンプルのウェブログモデルを使用すると、ビューでは、これは最適化を試みる前のコードです。

myblog = Blog.objects.get(pk=1)

d={} #going to pass this to my template

# not using count()
d['num_of_entries'] = len(myblog.entry_set.all()) 

# not using exists()
d['is_jolly'] = bool(Entry.objects.filter(blog=myblog, headline__startswith='Jolly'))

# ... other code but no further use of database in this view

2番目のQuerySetは、最初のQuerySetのサブセットです。サブセットを取得するために純粋なPythonを使用する必要がありますか(したがって、1つのQuerySetのみを評価します-1つ少ないデータベース呼び出し)?

または、おそらく単に次のことをしますか?

# other code as above

d['num_of_entries'] = myblog.entry_set.count()

d['is_jolly'] = Entry.objects.filter(blog=myblog, headline__startswith='Jolly').exists()

# ... other code but no further use of database in this view
4

1 に答える 1

6

「データベースクエリをできるだけ少なくする」は正しい基準ではありません。また、これらのデータベースクエリによって実行される作業の量、およびデータベースからDjangoサーバーに転送されるデータの量についても考慮する必要があります。

あなたが求めているものを実装するための2つの方法を考えてみましょう。アプローチ1:

entries = myblog.entry_set.all()
num_of_entries = len(entries)
is_jolly = any(e.headline.startswith('Jolly') for e in entries)

アプローチ2:

num_of_entries = myblog.entry_set.count()
is_jolly = Entry.objects.filter(blog=myblog, headline__startswith='Jolly').exists()

アプローチ1には単一のデータベースクエリがありますが、そのクエリはのようになりますSELECT * FROM ENTRY WHERE ...潜在的に多数のエントリをフェッチし、ネットワークを介してすべてのコンテンツをDjangoサーバーに送信します。Djangoサーバーは、ほぼすべてのコンテンツを破棄します(実際に表示されるフィールドはフィールドのみですheadline)。

アプローチ2には2つのデータベースクエリがありますが、最初のクエリは1SELECT COUNT(*) FROM ENTRY WHERE ...つの整数のみをフェッチするaであり、2番目のクエリはSELECT EXISTS(...)1つのブール値のみをフェッチするaです。これらのクエリは一致するすべてのエントリをフェッチする必要がないため、データベースがクエリを最適化する可能性はさらに高くなります。

したがって、アプローチ2は、より多くのクエリを発行しますが、この場合ははるかに良く見えます。

于 2013-01-14T18:05:14.357 に答える