#python #python-3.x #django #postgresql
#python #python-3.x #django #postgresql
Вопрос:
У меня периодически возникает проблема с производительностью Django и Postgres при обновлении одной строки в небольшой таблице строк «< 1 м».
APM сообщает о проблеме в строке обновления, которая:
Model.objects.filter(id=model_id).update(field=True)
Предложение filter использует первичный ключ таблицы, а запрос, выполняемый django, является:
'UPDATE "model" SET "field" = true WHERE "model"."id" = 12345'
Ошибка возникает из-за того, что выполнение занимает более 5 секунд.
Этот код выполняется в задаче celery, которая получает идентификатор модели в качестве аргумента и выполняется обычно большую часть времени.
Я знаю, что это очень открытый вопрос, но любая идея или помощь в отношении того, что может произойти, приветствуется.
У меня заканчиваются Python 3.7, Django 2.0.13 и Postgres 9.5.
Комментарии:
1. Индексируются ли столбцы, участвующие в фильтре? Если вы запустите запрос непосредственно в Postgres с
EXPLAIN
перед ним, что он вернет?2. Я обновил вопрос с помощью этой информации. Спасибо.
3. Обновление вопроса, вероятно, где-то потерялось, потому что я не могу увидеть там информацию об индексе столбца ни
EXPLAIN
.4. Вы можете включить auto_explain для автоматической регистрации
EXPLAIN
для медленных запросов (может быть снижение производительности, если у вас много медленных запросов).5. Скорее всего, он заблокирован из-за блокировки. Вы можете установить log_lock_waits, чтобы он регистрировал ожидания блокировки дольше, чем deadlock_timeout.
Ответ №1:
Проблема возникла из-за того, что мы запускали задачу, но иногда она выполнялась до фиксации текущей транзакции, что приводило к блокировке.
Решение состояло в том, чтобы использовать перехват django on_commit следующим образом:
class DoSomethingTask(Task):
def apply_async(self, *args, **kwargs):
transaction.on_commit(
lambda: super(DoSomethingTask, self).apply_async(*args, **kwargs))
@app.task(base=DoSomethingTask,...)
def do_something(tutor_id):
...