Actualizar varios objetos a la vez en Django?

Estoy usando Django 1.9. Tengo una tabla de Django que representa el valor de una medida particular, por organización por mes, con valores sin procesar y percentiles:

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) 

Por lo general, hay alrededor de 10.000 por mes. Mi pregunta es si puedo acelerar el proceso de configuración de valores en los modelos.

Actualmente, calculo los percentiles recuperando todos los valores medidos durante un mes usando una consulta de filtro Django, convirtiéndolo en un dataframe de pandas y luego usando rankdata de rankdata para establecer rangos y percentiles. Hago esto porque los pandas y rankdata son eficientes, capaces de ignorar valores nulos y capaces de manejar valores repetidos de la manera que yo quiero, así que estoy contento con este método:

 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 

Sin embargo, luego necesito recuperar cada valor de percentil del dataframe y volver a establecerlo en las instancias del modelo. En este momento, hago esto iterando sobre las filas del dataframe y actualizando cada instancia:

 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() 

Esto es sorprendentemente lento. ¿Hay alguna forma eficiente de Django para acelerarlo, haciendo que una única base de datos escriba en lugar de decenas de miles? He comprobado la documentación , pero no puedo ver uno.

Las transacciones atómicas pueden reducir el tiempo empleado en el bucle:

 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() 

El comportamiento predeterminado de Django es ejecutarse en modo de confirmación automática. Cada consulta se confirma inmediatamente en la base de datos, a menos que se active una transacción.

Al utilizar with transaction.atomic() todas las inserciones se agrupan en una sola transacción. El tiempo necesario para confirmar la transacción se amortiza en todas las declaraciones de inserción adjuntas y, por lo tanto, el tiempo por instrucción de inserción se reduce considerablemente.