3 回答
TA贡献1801条经验 获得超15个赞
我发现的一种解决方案是在模型保存调用周围使用 try/ except 块。尝试添加传感器读数,大多数情况下都会成功,但如果发生碰撞,请处理该错误。确保抛出的异常正是由于该冲突而引起的,然后将时间戳增加一微秒(最小分辨率)。然后重复尝试保存传感器读数。由于首先发生的碰撞概率较低,因此这几乎总是会成功。下面是经过测试的代码,用于递归地处理递增时间戳直到成功。
class SensorReading(models.Model):
time = models.DateTimeField(primary_key=True, default=datetime.now)
sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
value = models.FloatField()
def save(self, *args, **kwargs):
self.save_increment_time_on_duplicate(*args, **kwargs)
def save_increment_time_on_duplicate(self, *args, **kwargs):
try:
super().save(*args, **kwargs)
except IntegrityError as exception:
if all (k in exception.args[0] for k in ("Key","time", "already exists")):
self.time = str(parse_datetime(self.time) + timedelta(microseconds=1))
self.save_increment_time_on_duplicate(*args, **kwargs)
更稳健的实现还可能在中止之前添加最大尝试次数。
TA贡献1810条经验 获得超4个赞
一般来说,我建议至少在某种程度上从 Django 中获取该传感器表的表管理,使用 psycopg2 或其他驱动程序进行插入,并在 上创建适当的主键,然后公开该表(或Sensor, time
在它)作为一个 Django 模型,它可以从中读取,如果需要的话,也许可以使用连接。这些应该写入一次,因此您不必处理更新,这通常就是它需要非复合主键的原因。在某些时候 Django 应该真正开始支持复合主键,但遗憾的是他们没有。
其他方法可能有效,但它们可能根本无法很好地扩展。因此,如果您关心摄取率,我可能会尝试不同的方法。
添加回答
举报