减少日志记录实体的写入操作数

时间:2017-11-07 14:04:01

标签: mysql spring hibernate spring-boot innodb

我遇到了使用Hibernate / MySQL的Spring Boot应用程序的问题。

应用程序接收传感器数据(每秒最多多次)并将传入数据保存为Hibernate实体。您可以在下面找到传感器日志实体的Java代码。

系统部署在Raspberry Pi上,后者使用SD卡作为内存。看起来非常(!)的大量写入操作会对SD卡造成太大压力而且会失败。开发Pi上使用的最后一张SD卡虽然质量很高,却持续了大约6个月。

我想减少每秒/分钟的写入次数。最理想的是,数据每5或10分钟保存一次。在电力短缺的情况下数据丢失不是问题。我已经研究过硬件解决方案,比如使用外部硬盘驱动器来存储数据库。我唯一的选择是使用RPi的SD卡。所以我的方法是通过配置Spring / Hibernate / MySQL来减少写操作。然而,经过一些研究后,我发现有一些不同的方法来实现这一目标,我不确定哪一种最适合我的需求。

1。幼稚

我可以编写一个接受实体并将它们存储到列表中的Spring组件,然后定期保存列表内容。这似乎是相当多的编程工作,我希望有一些方法可以更智能地实现这一点。

2。冬眠/ MySQL的/ InnoDB的

我发现InnoDB配置sysvar_innodb_flush_log_at_trx_commit看起来像我想做的那样。我可以使用这个配置让mysql连接每1秒只刷新一次,但这不是最佳的:

  • 1秒的间隔仍然太频繁
  • 此行为将适用于我的所有表格,但我只希望将其用于此特定表格

我确信有一种方法可以直接在Hibernate中定义这种行为,但我还没有找到它。

结论/问题

有没有办法达到预期的行为?基于快速研究的建议是否有意义,或者您有更好的建议可供调查?非常感谢有关此事的任何意见!

附录:实体代码:

@Table(
        name = "sensor_data_point",
        indexes = { @Index(name = "sdp_idx", columnList = "sensor_uid,name,created") }
)
@Entity
@EntityListeners({AuditingEntityListener.class})
public class SensorDataPoint {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "sensor_uid", length = 191)
    private String sensorUid;

    @Column(name = "name", length = 191)
    private String name;

    @Column(name = "value", length = 191)
    private String value;

    @CreatedDate
    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    // Constructor, Getters, Setters
    // ...

}

1 个答案:

答案 0 :(得分:0)

sync_binlog=OFF

由于您可以丢失一些数据,请考虑以下事项。对于讨论,让我们说你可以丢失1分钟的数据。

有一个名为MEMORY的额外Gather表,您可以在其中收集传感器数据,而不是Real InnoDB表。并且每分钟都有EVENTcron个工作,并执行以下操作:

CREATE TABLE Tmp LIKE Gather;   -- copy schema
RENAME TABLE Gather TO Inserter, Tmp TO Gather;  -- atomic, fast
INSERT INTO Real  SELECT * FROM Inserter;   -- batched, single transaction, etc

注意:

  • 可能你每分钟只写一个(或几个)块。
  • SELECT期间,您可以转换数据(如有必要)。

此外:

  • 摆脱不必要的索引;它们导致对SSD的写入不足以及#34;磨损均衡"。
  • 考虑在事件中写入摘要表。或者等到一天结束。
  • 更多讨论:http://mysql.rjweb.org/doc.php/staging_table - 重点介绍如何以比磁盘处理数据更快的速度提取数据,这是(以一种不正常的方式)你的情况。我在此答案中添加了MEMORY,因为它符合您的情况。
  • 最小化您使用的数据类型的大小。 (减少要写入的块数。)
  • 在可行的情况下归一化。 (减少要写入的块数。)
  • 一旦您按照我的建议,您将不再需要担心innodb_flush_log_at_trx_commit
  • 似乎MySQL 8.0将有一些技术可以减少磁盘命中率。但我还没准备好指出具体细节。

请提供生成的SHOW CREATE TABLEINSERT代码的SQL。可能会有更多建议给你。有多少传感器? diff行或diff cols中的传感器值是否不同?等