Как ускорить запросы mongoengine
Если у меня есть два объекта, как:
class User(Document):
name = StringField()
following = ListField(ReferenceField('User'))
meta = {
'indexes': [
'following',
]
}
class Media(Document):
owner = ReferenceField('User')
url = StringField()
is_hidden = BooleanField()
posted_date = Date
meta = {
'indexes': [
'owner',
'posted_date',
'is_hidden',
]
}
и когда я хочу найти следующее условие, когда оно не скрыто, и его владельцем является тот, за кем я следую, и он был недавно опубликован, у меня появляется запрос, подобный этому:
user = User.objects.first()
Media.objects(Q(owner__in=user.following) &
Q(is_hidden=False) &
Q(posted_date__gte=dt.now()-dt.timedelta(days=3))
который не масштабируется и становится намного медленнее. Что я могу сделать, чтобы повысить производительность этих типов сложных запросов?
2 ответа
1) Использование User.objects.get(id=user_id)
вместо first()
, Хотя я не совсем уверен, если это будет иметь значение, я думаю, что да, и это find
операция, при которой MongoDB возвращает курсор, а mongoengine выполняет итерацию к первому документу. Вместо, get()
делает findOne
и возвращает только 1 документ. Если я ошибаюсь, кто-то должен исправить меня, пожалуйста.
2) Используйте составной индекс (не несколько отдельных индексов), так как ваш запрос использует несколько полей (пример здесь также):
meta = {
'indexes': [
('owner', 'posted_date', 'is_hidden',)
]
}
3) Ограничьте возврат данных только в те поля, которые вам нужны, спроецируйте ваши поля, используя only()
Используйте объяснение () в вашем запросе, чтобы изучить его и улучшить его в oder, чтобы достичь покрытого запроса.
Если вы планируете использовать mongoengine в производстве с большими документами, взгляните на этот пост: https://github.com/MongoEngine/mongoengine/issues/1230
Мы использовали mongoengine, но он стал очень медленным по причине, описанной в посте выше.
В итоге мы переписали весь наш бэкэнд, используя https://github.com/mongodb/pymodm Это относительно новый проект для команды mongodb. Мы используем его с Django, и он работает намного быстрее, чем mongoengine с точно такой же базой данных.