データベースに可変数のフィールドを持つ測定値を保存する最も効率的な方法は何ですか?
質問
環境センサーから測定値を収集するデータ収集システムがあり、河川または水路を流れる水の速度を測定します。各測定では、固定数の値(日付、時刻、温度、圧力など)と速度値のリストが生成されます。
もともとセンサーは3つの速度値を提供していたので、FireBirdデータベースの単一テーブルの独自の列に各値を保存しました。その後、最大9つの速度値を出力できるセンサーが導入されたため、さらに6列追加しました。ほとんどのセンサーは9個未満の値を使用しますが、ほとんどの列にゼロが含まれていれば問題ないと考えています。
しかし今、私は1から256の値を出力できる新しい世代に直面しています。特にほとんどの測定にはまだ3から9の値しか含まれていないため、別の247列を追加するのはあまり効率的ではないと思います。
測定値は10分ごとに収集され、データベースには30から50個のセンサーのすべてのデータが含まれているため、データの合計量は数年後に非常に重要になりますが、ランダムな期間の概要/グラフを生成できる必要があります。
では、値の変数リストを保存する最も効率的な方法は何でしょうか?
各レコードには固有のIDがあるため、すべての速度値を別々のテーブルに保存でき、各値にはレコードIDのタグが付けられていると思います。これはあまり効率的ではなく、しばらくすると非常に遅くなると感じています。
解決
効率的なインデックスを使用すると、データベースはテーブル内の大量のデータを処理できます。したがって、次のテーブル構造を使用できます。
create table measurements (
id,
seq integer, -- between 1 and 256
ts timestamp, -- Timestamp of the measurement
value decimal(...)
)
id
、 id、seq
および ts
にインデックスを作成します。これにより、データを効率的に検索できます。データベースに不信がある場合は、数百万行を挿入し、数回の選択を実行して、どれだけうまくいくかを確認してください。
比較のために、ここには1億1,200万行のOracleデータベースがあり、タイムスタンプまたはIDで120ms(0.12s)以内にレコードを選択できます
他のヒント
テキストフィールドにシリアル化されたデータを保存できます。たとえば、測定値を次のようにJSONエンコードします。
[<velocity-value-1>, <velocity-value-2>, ...]
次に、コード内で、クエリ後に値を逆シリアル化します。
これは、保存された値ではなく、他のフィールドのみでクエリをフィルタリングする場合に有効です。値でフィルタリングすると、 WHERE
句で値を使用すると悪夢になります。
2番目のテーブルに行きます:
table measurements (Id, DateTime, Temperature, Pressure)
table velocity (Id, MeasurementId, Sequence, Value)
Velocity.MeasurementId
は Measurements.Id
を参照します。
Velocity.Sequence
は、その測定値の速度値のインデックスです(1〜256)。
これらのテーブルにできるだけ現実に近いデータを入力し、sqlステートメントをテストして最適なインデックスを見つけます。