2016-04-20 2 views
4

Я использую Django 1.9. У меня есть таблица Джанго, которая представляет ценность конкретной меры, организация по месяцам, с сырыми значениями и процентилями:Обновление нескольких объектов сразу в Django?

class MeasureValue(models.Model): 
    org = models.ForeignKey(Org, null=True, blank=True) 
    month = models.DateField() 
    calc_value = models.FloatField(null=True, blank=True) 
    percentile = models.FloatField(null=True, blank=True) 

Есть, как правило, 10 000 или около того в месяц. Мой вопрос заключается в том, могу ли я ускорить процесс установки значений на моделях.

В настоящее время я вычисляю процентили, получая все измеренные значения в течение месяца, используя запрос фильтра Django, преобразовывая его в рамку данных pandas, а затем используя scipy's rankdata для установки рангов и процентилей. Я делаю это потому, что панды и rankdata эффективны, способны игнорировать нулевые значения, и способны обрабатывать повторяющиеся значения в том, что я хочу, так что я доволен этим методом:

records = MeasureValue.objects.filter(month=month).values() 
df = pd.DataFrame.from_records(records) 
// use calc_value to set percentile on each row, using scipy's rankdata 

Однако, я тогда нужно для извлечения каждого значения процентиля из фрейма данных и установки его обратно в экземпляры модели. Прямо сейчас я делаю это путем перебора строк в dataframe, и обновление каждого экземпляра:

for i, row in df.iterrows(): 
    mv = MeasureValue.objects.get(org=row.org, month=month) 
    if (row.percentile is None) or np.isnan(row.percentile): 
     row.percentile = None 
    mv.percentile = row.percentile 
    mv.save() 

Это удивительно довольно медленно. Есть ли эффективный способ Django ускорить его, создав единую базу данных, а не десятки тысяч? У меня есть checked the documentation, но не вижу его.

+0

Вы посмотрели на ['QuerySet.update()'] (https://docs.djangoproject.com/en/1.9/ref/models/querysets/#update)? –

+0

@ Two-BitAlchemist Я не уверен, что это помогает, учитывая, что мне нужно установить другое значение для каждой строки ...? – Richard

+0

ой, я пропустил это требование, извините –

ответ

8

Атомные операции могут сократить время, затрачиваемое в цикле:

from django.db import transaction 

with transaction.atomic(): 
    for i, row in df.iterrows(): 
     mv = MeasureValue.objects.get(org=row.org, month=month) 

     if (row.percentile is None) or np.isnan(row.percentile): 
      # if it's already None, why set it to None? 
      row.percentile = None 

     mv.percentile = row.percentile 
     mv.save() 

поведение Джанго по умолчанию для запуска в режиме автоматической фиксации. Каждый запрос немедленно передается в базу данных, если транзакция не является активным.

С помощью with transaction.atomic() все вставки сгруппированы в одну транзакцию. Время, необходимое для совершения транзакции, амортизируется по всем прилагаемым операторам вставки, и поэтому время для инструкции вставки значительно уменьшается.

+0

Спасибо. Почему это сокращает время? Документация не помогает https://docs.djangoproject.com/en/1.9/topics/db/transactions/#controlling-transactions-explicitly – Richard

+0

проверить мое обновление – ahmed

Смежные вопросы