web-dev-qa-db-ja.com

時系列データを効率的に保存する:mySQLまたはフラットファイル? WHERE条件の多くのテーブル(またはファイル)またはクエリ?

数千の(しかしすぐに数百万になる可能性がある)実世界のハードウェアセンサーの時系列データを保存するための最良の方法は何ですか?センサー自体は異なり、1つの変数をキャプチャするだけのものもあれば、最大12個の変数をキャプチャするものもあります。これらの値を1時間ごとに保存する必要があり、xより古いデータを削除したくありません。つまり、データは増え続けます。

現在、mySQLデータベースを使用してこれらの時系列を保存しています(これは、すべてのセンサーのニース時系列グラフを表示するWebフロントエンドにも役立ちます)。センサーごとに1つのテーブルがあり、現在は合計で約11​​000に相当します。各テーブルには、「timestamp、value1、[value2] ...」のようなレイアウトがあります。

データベースの主なタスクは、挿入/更新(1時間に1回)よりも多くの選択(誰かがグラフを見るたび)です。グラフを表示するための選択クエリは、単に「SELECT * FROM $sensor_id ORDER BY timestamp "なので、selectステートメントから情報を取得するのは非常に簡単で効率的です。

ただし、LOCKの制限に遭遇したため、データベースのバックアップ時にすでに多くのテーブルがあると、いくつかの問題が発生します(例:mysqldump:エラーが発生しました:23:ファイル './database/table_xyz.MYD'を開くときにリソースが不足しています(エラーコード:24 )LOCK TABLESを使用する場合 ")そのエラーを回避することはできますが、明らかにそれで私は考えました...

したがって、実際の質問は、サブ質問に分解されます。

  • センサーごとに1つのテーブルを使用するという私のアプローチはどれほど悪いですか?数千のテーブルではなく、数百万のテーブルがある場合はどうなりますか(近い将来、その数のセンサーを処理する必要があるかもしれません)。
  • すべてのセンサーのデータを1つの結合されたテーブルに格納し、sensor_idを保持する追加の列を追加すると、selectステートメントの速度が大幅に低下する可能性があるため(SELECT * from all_sensors どこ sensor_id = '$ sensor_id')?センサーが異なれば測定値も異なるため、すべてのセンサーに独自のテーブルがある場合、このテーブルには1つから数個ではなく、数十個の列があることに注意してください。
  • また、時系列データをmySQLではなく、フラット(CSV)ファイルに保存することも考えました。フロントエンド(dygraphs)に使用するグラフライブラリはCSVファイルを適切に処理します(さらに、これらをダウンロードできるようにするオプションがあります。これはボーナスですが、現在の要件ではありません)。他のフロントエンド関連のもののためにデータベースがまだ必要ですが、それは11000の代わりに数十のテーブルを持つことを意味します(またはセンサーを追加するとさらに多くなります)。
  • テーブルごとに1つのファイルを作成すると、最終的にファイルシステムの制限に遭遇する可能性があります(これは、ext3パーティションであるため、ディレクトリあたり最大32kのファイルが制限されます)。したがって、ここでも上記と同じ質問が当てはまります。次に、すべてのセンサーのデータを保持する1つの大きなファイルに保存する必要がありますか?グラフ作成ライブラリは、誰かがグラフを見るたびに、はるかに大きなファイルをメモリに読み込む必要があるため、これはおそらく私の読み取りをさらに遅くしますか?

あなたならどうしますか?

ありがとう!

13
user1891659

この質問に答えるには、まず、直面している実際の問題を分析する必要があります。

本当の問題は、データの書き込みと取得の最も効率的な組み合わせです。

結論を確認しましょう。

  • 数千のテーブル-まあ、それはデータベースの目的に違反し、操作を難しくします。また、何も得られません。まだディスクシークが関係していますが、今回は多くのファイル記述子が使用されています。また、テーブル名を知っている必要があり、それらは何千もあります。また、データベースの目的であるデータを抽出することも困難です。レコードを簡単に相互参照できるようにデータを構造化することです。何千ものテーブル-パフォーマンスからは効率的ではありません。視点。使用の観点からは効率的ではありません。下手な選択。

  • csvファイル-コンテンツ全体が一度に必要な場合は、データのフェッチに最適です。しかし、データの操作や変換にリモートで適しているとは言えません。特定のレイアウトに依存しているという事実を考えると、CSVへの書き込みには特に注意する必要があります。これが数千のCSVファイルに拡大した場合、あなたは自分自身を支持しませんでした。 SQLのオーバーヘッド(それほど大きくはありません)をすべて削除しましたが、データセットの一部を取得するために何もしませんでした。また、履歴データのフェッチや相互参照に問題があります。下手な選択。

理想的なシナリオは、構造を変更することなく、効率的かつ迅速な方法でデータセットの任意の部分にアクセスできることです。

そして、これがまさに私たちがリレーショナルデータベースを使用する理由であり、多くのRAMを備えたサーバー全体をそれらのデータベース専用にする理由です。

あなたの場合、MyISAMテーブル(.MYDファイル拡張子)を使用しています。これは、当時使用されていたローエンドのハードウェアに最適な古いストレージ形式です。しかし、最近では、優れた高速のコンピューターがあります。そのため、InnoDBを使用し、多くのRAMを使用できるようにして、I/Oコストを削減します。それを制御する問題の変数はinnodb_buffer_pool_sizeと呼ばれます。意味のある結果を生成します。

質問に答えるには、効率的で満足のいく解決策は、センサー情報(ID、タイトル、説明)を格納する1つのテーブルと、センサーの読み取り値を格納する別のテーブルを使用することです。十分なRAMまたは十分に高速なストレージ(SSD)を割り当てます。テーブルは次のようになります。

CREATE TABLE sensors ( 
    id int unsigned not null auto_increment,
    sensor_title varchar(255) not null,
    description varchar(255) not null,
    date_created datetime,
    PRIMARY KEY(id)
) ENGINE = InnoDB DEFAULT CHARSET = UTF8;

CREATE TABLE sensor_readings (
    id int unsigned not null auto_increment,
    sensor_id int unsigned not null,
    date_created datetime,
    reading_value varchar(255), -- note: this column's value might vary, I do not know what data type you need to hold value(s)
    PRIMARY KEY(id),
    FOREIGN KEY (sensor_id) REFERENCES sensors (id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = UTF8;

InnoDBは、デフォルトで、データベース/インストール全体に1つのフラットファイルを使用します。これにより、OS /ファイルシステムのファイル記述子の制限を超える問題が軽減されます。作業データセットをメモリに保持するために5〜6ギガのRAMを割り当てる場合、数千、または数千万のレコードでさえ問題にはなりません。これにより、次の場所にすばやくアクセスできます。データ。

私がそのようなシステムを設計する場合、これは私が(個人的に)行う最初のアプローチです。そこから、その情報をどのように処理する必要があるかに応じて、簡単に調整できます。

7
N.B.