我正在使用 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 过滤器查询检索一个月的所有测量值来计算百分位数,将其转换为熊猫数据框,然后使用 scipy 的 rankdata
设置排名和百分位数。我这样做是因为 pandas 和 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
但是,然后我需要从数据框中检索每个百分位值,并将其设置回模型实例。现在我通过遍历数据框的行并更新每个实例来做到这一点:
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 方法可以通过写入单个数据库而不是数万个来加快速度?我已经 检查了文档,但看不到一个。
原文由 Richard 发布,翻译遵循 CC BY-SA 4.0 许可协议
原子事务可以减少循环中花费的时间:
Django 的默认行为是以自动提交模式运行。每个查询都会立即提交给数据库,除非事务处于活动状态。
通过使用
with transaction.atomic()
所有插入都被分组到一个事务中。提交事务所需的时间分摊到所有包含的插入语句中,因此每个插入语句的时间大大减少。