Djangoアプリのデータベースクエリを最適化しようとしています。簡単な例を次に示します。
class Label(models.Model):
name = models.CharField(max_length=200)
# ... many other fields ...
class Thing(models.Model):
name = models.CharField(max_length=200)
labels = models.ManyToManyField(Label)
すべてLabelのsとThingsをフェッチし、それらをJSONデータ構造に配置する関数があります。ここで、sはs(主キー)を使用してsをThing参照します。このようなもの:Labelid
{
'labels': [
{ 'id': 123, 'name': 'label foo' },
...
],
'things': [
{ 'id': 45, 'name': 'thing bar', 'labels': [ 123, ... ] },
...
]
}
Djangoを使用してそのようなデータ構造を取得する最も効率的な方法は何ですか?LsとTsがあり、 平均がxsであるとします。Label ThingThing Label
方法1:
data = {}
data['labels'] = [model_to_dict(label) for label in Label.objects.all()]
data['things'] = [model_to_dict(thing) for thing in Thing.objects.all()]
これにより、(1 + 1 + T)データベースクエリが作成されます。これは、それぞれのsを個別model_to_dict(thing)にフェッチする必要があるためです。LabelThing
方法2:
data = {}
data['labels'] = [model_to_dict(label) for label in Label.objects.all()]
data['things'] = [model_to_dict(thing) for thing in
Thing.objects.prefetch_related('labels').all()]
これにより、(1 + 1 + 1)データベースクエリのみが作成されます。Thingこれは、フェッチされたLabelsが単一の追加クエリでプリフェッチされるようになったためです。
これはまだ満足のいくものではありません。 prefetch_related('labels')同じの多くのコピーをフェッチしLabelますが、必要なのはそれらのコピーだけですid。idのLabelsのみをプリフェッチする方法はありますか?試しprefetch_related('labels__id')ましたが、うまくいきませんでした。また、 Tが大きい(数百)ため、大きな句prefetch_related('labels')を含むSQLクエリが生成されることも懸念されます。Lははるかに小さい(<10)ので、代わりにこれを行うことができます。IN
方法3:
data = {}
data['labels'] = [model_to_dict(label) for label in
Label.objects.prefetch_related('thing_set').all()]
things = list(Thing.objects.all())
# plug in label ids by hand, and also fetch things that have zero labels
# somehow
これにより、句が小さくなりますが、 aに複数のsがある場合、重複するsをフェッチするINため、それでも満足のいくものではありません。prefetch_related('thing_set')ThingThingLabel
概要:
LabelとThingで接続されていManyToManyFieldます。とにかくすべて Labelのsとsをフェッチしています。Thingでは、どうすれば多対多の関係を効率的に取得できますか?