Предположим, теперь у меня есть 2 модели, A и B.
И между A и B существует отношение многие ко многим
class B(models.Model):
score_b = model.IntegerField()
class A(models.Model):
b = models.ManyToMany(B, related_name='b_set')
score_a = models.IntegerField()
name = models.CharField(unique=True)
==
Рабочий процесс - сначала я фильтрую некоторый экземпляр A по score_a
и использую их для запроса B с score_b
Так что наивный фрагмент кода может выглядеть так (Решение A)
## Solution A
stuff = {}
a_list = A.objects.filter(score_a__gte=100)
for a in a_list:
qs = a.b_set.filter(score_b__gte=200)
stuff[a.name] = [b.score for b in qs]
return stuff
Но я стараюсь изо всех сил улучшить производительность
И предыдущий код, похоже, требует 1 + len(a_list)
доступ к базе данных
Так что я бы попробовал использовать prefetch_related
(Решение B)
## Solution B
stuff = {}
a_list = A.objects.filter(score_a__gte=100).prefetch_related('b')
for a in a_list:
qs = a.b_set.filter(score_b__gte=200)
stuff[a.name] = [b.score for b in qs]
return stuff
Однако кажется, что кэшированный b
будет игнорироваться, поскольку filter
- это другой запрос.Таким образом, приведенный выше код не помогает вообще.
Теперь ему требуется 1 + 1 + len(a_list)
доступ к базе данных из-за дополнительного prefetch_related
запроса
Теперь я придумаю еще одну идею - фильтр b вpython для уменьшения доступа к базе данных (Решение C)
## Solution C
stuff = {}
a_list = A.objects.filter(score_a__gte=100).prefetch_related('b')
for a in a_list:
qs = a.b_set.all()
temp = [b.score for b in qs if b.score >= 200]
stuff[a.name] = temp
return stuff
И теперь количество обращений к базе данных должно упасть до 1
, что является удивительным
Но я беспокоюсь о выполнении фильтрав python может быть намного медленнее, чем фильтр в базе данных
Будет ли он работать в Solution C быстрее, чем Solution A?
Спасибо!
Edit
Я отредактировал фрагмент кода.
Извините за мой плохой английский и плохое описание, которые приводят к недоразумению.
Мой вопрос о том, должен ли я всегда выполнять фильтрацию в базе данных или это нормально делатьэто в Python, особенно когда последний может сохранить некоторые / многие доступ к базе данных.