У меня есть Flask приложение с RESTful API. Один из вызовов API - это вызов "массового upsert" с полезной нагрузкой JSON. Я борюсь с работой.
Первое, что я пробовал, это использовать merge-result
для объекта Query
, потому что...
Это оптимизированный метод, который объединит все сопоставленные экземпляры, сохраняя структуру строк результата и неотображаемых столбцов с меньшими затратами на методы, чем метод вызова Session.merge() явно для каждого значения.
Это был начальный код:
class AdminApiUpdateTasks(Resource):
"""Bulk task creation / update endpoint"""
def put(self, slug):
taskdata = json.loads(request.data)
existing = db.session.query(Task).filter_by(challenge_slug=slug)
existing.merge_result(
[task_from_json(slug, **task) for task in taskdata])
db.session.commit()
return {}, 200
Запрос на эту конечную точку с ~ 5000 записями, все из которых уже существуют в базе данных, возвращает более 11 м:
real 11m36.459s
user 0m3.660s
sys 0m0.391s
Поскольку это было бы довольно типичным вариантом использования, я начал изучать альтернативы для повышения производительности. Против моего лучшего суждения я попытался merge
сеанс для каждой отдельной записи:
class AdminApiUpdateTasks(Resource):
"""Bulk task creation / update endpoint"""
def put(self, slug):
# Get the posted data
taskdata = json.loads(request.data)
for task in taskdata:
db.session.merge(task_from_json(slug, **task))
db.session.commit()
return {}, 200
К моему удивлению, это оказалось более чем в два раза быстрее:
real 4m33.945s
user 0m3.608s
sys 0m0.258s
У меня есть два вопроса:
- Почему вторая стратегия использует
merge
быстрее, чем предположительно оптимизированная первая, которая используетmerge_result
? - Какие еще стратегии следует использовать для оптимизации этого, если таковые имеются?