2017-11-07 8 views
0

Hibernate/MySQLを使用するSpringブートアプリケーションで問題が発生しています。ロギングエンティティの書き込み操作数を減らす

アプリケーションはセンサデータ(1秒間に複数回)を受信し、着信データをHibernateエンティティとして保存します。以下のセンサーログエンティティのJavaコードを見つけることができます。

システムは、メモリとしてSDカードを使用するRaspberry Piに導入されました。非常に(!)書き込み操作の数が多いとSDカードに負荷がかかり過ぎるように見えます。開発Piで使用された最後のSDカードは、高品質であるにもかかわらず約6ヶ月間続きました。

1秒あたりの書き込み回数を減らしたいとします。最適には、データは5または10分ごとに1回保存されます。電力不足の場合のデータ損失は問題ではありません。私はすでにデータベース用の外付けハードドライブを使用するようなハードウェアソリューションを検討しました。私の唯一の選択肢は、RPiのSDカードを使用することです。だから私のアプローチは、Spring/Hibernate/MySQLを設定することによって書き込み操作を減らすことです。しかし、いくつかの研究の後、私はこれを達成するためのいくつかの異なる方法があることを発見した。そして、どちらが私のニーズに最も適しているかわからない。

1.ナイーブ

私はエンティティを受け入れ、リストにそれらを保存するSpringコンポーネントを書き、その後、定期的にリストの内容が保存されます可能性があります。これはかなりの量のプログラミング作業のようですが、これをよりスマートな方法で実現する方法がいくつかあると思います。

2.休止/ MySQLの/ InnoDBの

私は一種の、私がやりたいように見えるのInnoDB設定sysvar_innodb_flush_log_at_trx_commitを発見しました。私は、MySQLの接続のみが1秒ごとにフラッシュするには、この設定を使用することができますが、これは最適ではありません。

  • は、1秒の間隔があまりにも頻繁に
  • この動作は私のテーブルのすべてに適用される、まだですしかし、私はこの特定のテーブルのためだけにしたいです

MySQLの設定を直接設定するのではなく、この動作を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 
    // ... 

} 

答えて

0

sync_binlog=OFF

あなたは、いくつかのデータ量が失われることを可能にすることができるので、以下のことを考慮してください。議論のために、1分のデータを失う可能性があるとしましょう。

Real InnoDBテーブルではなく、センサデータを収集するMEMORYというテーブルがGatherとなっています。

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 

注:

  • おそらくあなたは毎分だけ1(または少数)のブロックを書いているし、毎分に沿って来て、次んEVENTcron仕事をしています。
  • SELECTの間に、データを変換することができます(必要な場合)。また

  • は、不要なインデックスを取り除きます。不適切な「ウェアレベリング」を持つSSDへの書き込みを引き起こします。
  • イベントの要約表への書き込みを検討してください。または、終わりまで待つ。
  • さらに詳しい説明:http://mysql.rjweb.org/doc.php/staging_table - これは、ディスクが処理できるよりも速くデータを取り込む方法に焦点を当てています。この回答にMEMORYを追加しました。に該当するからです。
  • 使用するデータ型のサイズを最小限に抑えます。 (書き込むブロック数を減らす)
  • 実用的なところで正規化する。あなたが私のアドバイスに従っていると(書き込みにブロックの数を減らすために。)
  • 、あなたは、もはやについてinnodb_flush_log_at_trx_commit
  • のMySQL 8.0は、ディスクのヒットに戻ってカットし、いくつかのテクニックがありますように思えを心配する必要はありません。しかし、私は具体的なことを指摘する準備ができていません。

生成されたSHOW CREATE TABLEINSERTコードのSQLを入力してください。あなたに与えるより多くの提案があるかもしれません。何個のセンサー?異なるセンサー値は、diff行またはdiff列にありますか?等

+0

この提案をありがとう!私はメモリテーブルを実装し、それは非常にうまくいくようです – Jan

関連する問題