Я использую Django с sqlite бэкендом, и производительность записи является проблемой. Я могу получить высшее образование к "надлежащему" дб на некотором этапе, но в настоящий момент я застреваю с sqlite. Я думаю, что мои проблемы производительности записи, вероятно, связаны с тем, что я создаю большое количество строк, и по-видимому каждый раз I save()
один это блокирует, разблокировав и синхронизируя DB на диске.
Как я могу агрегировать большое количество save()
вызовы в операцию единой базы данных?
ИЗМЕНИТЬ: commit_on_success
устарел и был удален в Django 1.8. Вместо этого используйте transaction.atomic
. См. Ответ Фрейзера Харриса .
На самом деле это легче сделать, чем вы думаете. Вы можете использовать транзакций в Django. Эти пакетные операции с базой данных (в частности, сохранение, вставка и удаление) объединены в одну операцию. Я обнаружил, что самый простой в использовании - commit_on_success
. По сути, вы превращаете операции сохранения базы данных в функцию, а затем используете декоратор commit_on_success
.
from django.db.transaction import commit_on_success
@commit_on_success
def lot_of_saves(queryset):
for item in queryset:
modify_item(item)
item.save()
Это значительно увеличит скорость. Вы также получите возможность отката, если какой-либо из элементов выйдет из строя. Если у вас есть миллионы операций сохранения, возможно, вам придется фиксировать их блоками, используя commit_manually
и transaction.commit ()
, но мне это редко нужно.
Надеюсь, что это поможет,
Уилл
"Как я могу объединить большое количество вызовов save() в одну операцию с базой данных?"
Вам не нужно этого делать. Django уже управляет кэшем за вас. Вы не сможете улучшить его кэширование в БД, пытаясь возиться с сохранениями.
"проблемы с производительностью записи, вероятно, связаны с тем, что я создаю большое количество строк"
Верно.
SQLite довольно медленный. Так оно и есть. Запросы выполняются быстрее, чем в большинстве других БД. Записи довольно медленные.
Рассмотрим более серьезное изменение архитектуры. Загружаете ли вы строки во время веб-транзакции (т.е. массовая загрузка файлов и загрузка БД из этих файлов)?
Если вы выполняете массовую загрузку внутри веб-транзакции, остановитесь. Вам нужно сделать что-то более умное. Используйте celery или какой-нибудь другой "пакетный" инструмент для выполнения загрузки в фоновом режиме.
Мы стараемся ограничиться валидацией файлов в веб-транзакции и выполнять загрузку, когда пользователь не ждет своей страницы HTML.