Агрегирование save () в Django? - PullRequest
       1

Агрегирование save () в Django?

40 голосов
/ 03 августа 2010

Я использую Django с бэкэндом sqlite, и производительность записи является проблемой.Я могу перейти к «правильному» БД на каком-то этапе, но на данный момент я застрял с sqlite.Я думаю, что мои проблемы с производительностью записи, вероятно, связаны с тем, что я создаю большое количество строк, и, вероятно, каждый раз, когда я save() один, это блокирует, разблокирует и синхронизирует БД на диске.Как я могу объединить большое количество save() вызовов в одну операцию базы данных?

Ответы [ 4 ]

66 голосов
/ 03 августа 2010

РЕДАКТИРОВАНИЕ: 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(), но мне это редко требуется.

Надеюсь, это поможет,

Будет

54 голосов
/ 23 марта 2015

Новое в Django 1.6 - atomic, простой API для управления транзакциями БД .Дословно скопированный из документов:

atomic может использоваться как декоратор :

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

и как менеджер контекста :

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

Legacy django.db.transaction функции autocommit(), commit_on_success() и commit_manually() устарели и будут удалены в Django 1.8.

6 голосов
/ 06 сентября 2018

Я думаю, что это метод, который вы ищете: https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create

Код, скопированный из документации:

Entry.objects.bulk_create([
    Entry(headline='This is a test'),
    Entry(headline='This is only a test'),
])

Что на практике выглядело бы так:

my_entries = list()
for i in range(100):
    my_entries.append(Entry(headline='Headline #'+str(i))

Entry.objects.bulk_create(my_entries)

Согласно документации, выполняется один запрос независимо от размера списка (максимум 999 элементов в SQLite3), чего нельзя сказать о декораторе atomic.

Есть важное различие, которое нужно сделать. По мнению ОП, похоже, что он попытался массово создать вместо массового сохранения . Декоратор atomic - самое быстрое решение для сохранения , но не для создания .

0 голосов
/ 03 августа 2010

«Как объединить большое количество вызовов save () в одну операцию базы данных?»

Вам не нужно.Django уже управляет кешем для вас.Вы не можете улучшить его кэширование в БД, пытаясь возиться с сохранениями.

"Проблемы с производительностью записи, вероятно, связаны с тем, что я создаю большое количество строк"

Правильно.

SQLite довольномедленный.Так оно и есть.Запросы выполняются быстрее, чем в большинстве других БД.Пишет довольно медленно.

Рассмотрим более серьезные изменения архитектуры.Загружаете ли вы строки во время веб-транзакции (т.е. массовую загрузку файлов и загрузку БД из этих файлов)?

Если вы выполняете массовую загрузку внутри веб-транзакции, остановитесь.Вы должны сделать что-то умнее.Используйте celery или используйте другое «пакетное» средство для выполнения ваших загрузок в фоновом режиме.

Мы пытаемся ограничиться проверкой файлов в веб-транзакции и выполняем загрузки, когда пользователь нев ожидании своей страницы HTML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...