バックグラウンド
約2000個のセンサーのネットワークがあり、各センサーには10分間隔で収集する約100個のデータポイントがあります。これらのデータポイントは通常int値ですが、一部は文字列と浮動小数点です。このデータは90日間保存する必要がありますが、可能であればさらに保存し、効率的です。
データベース設計
もともとこのプロジェクトを担当していたとき、私は各センサーにコンマ区切りファイルを書き込むC#アプリを作成しました。当時はそれほど多くはありませんでしたが、誰かがトレンドを調べたいときは、ExcelでCSVを開き、必要に応じてグラフ化しました。
事態は拡大し、MySQLデータベースに切り替えました。センサーごとにテーブルを作成しました(はい、たくさんのテーブルがあります!)。うまく機能していますが、いくつかの制限があります。非常に多くのテーブルがあるため、特定の値を検索するときにすべてのセンサーからデータを検索するクエリを作成することは明らかに不可能です。
次のバージョンでは、Microsoft SQL Server Expressに切り替えて、すべてのセンサーデータを1つの大きなテーブルに入れました。これも機能し、クエリを実行して、関心のあるすべてのセンサーから値を見つけることができます。ただし、Expressバージョンでは10 GBの制限に達したため、SQL Server Standardに投資するのではなく、MySQLに切り替えることにしました。
質問
私はMySQLのパフォーマンスとスケーラビリティに満足していますが、1つのテーブルにすべてを収めたアプローチに固執するのが最善かどうかはわかりません。1つのテーブルで10 GBが異なるデザインを要求しているようです。グラフ作成のためにデータを照会する必要性はまだあることに言及する必要があります。たとえば、1つのセンサーの温度データを90日間にわたってグラフ化する照会のパフォーマンスの問題があることを懸念しています。(つまり、グラフは、目的のセンサーを分離するためだけにSQLがデータの山を並べ替えるのを待たずに、すぐに作成できるものでなければなりません。)
パフォーマンスを向上させるために、このテーブルを何らかの方法で分割する必要がありますか?それとも、そのような大きなテーブルを持つことは珍しくありませんか?
Sensor ID列とTimestamp列にインデックスがあります。これは、ほとんどすべてのクエリの定義境界です。(つまり、時間Aから時間BまでのセンサーXのデータを取得します)。
シャーディングとパーティション分割について少し読んだことがありますが、この場合は適切であるとは感じません。
編集:
これまでのコメントと回答に基づいて、いくつかの追加情報が役立つ場合があります。
無期限のストレージではない:現在、90日以上データを保存していません。毎日、90日より古いデータを削除するクエリを実行します。将来的に重要になる場合は、さらに保管しますが、今のところはそれで十分です。これにより、サイズを抑えることができ、パフォーマンスが向上します。
エンジンタイプ:元のMySQL実装はMyISAMを使用しました。今回は、新しい実装(多くではなく1つのデータテーブル)用にテーブルを作成するときに、デフォルトでInnoDBを使用しました。どちらか一方に要件があるとは思わない。
正規化:もちろん、データ収集テーブルの他に他のテーブルがあります。これらのサポートテーブルには、センサーのネットワーク情報、ユーザーのログイン情報などが保存されます。正規化することはあまりありません(私の知る限り)。データテーブルに非常に多くの列があるのは、各センサーからの変数が非常に多いためです。(複数の温度、光レベル、気圧など)私にとっての正規化とは、冗長なデータや繰り返しグループがないことを意味します。(少なくとも1NFの場合)特定のセンサーの場合、特定の時間にすべての値を保存するには1行のデータが必要で、1:N関係は関係していません(私は見ています)。
テーブルを機能的に分解し、(たとえば)1つのテーブルにすべての温度関連の値を作成し、別のテーブルにすべての空気圧関連の値を作成できます。これにより、温度のみのクエリを実行するユーザーの効率が向上する可能性がありますが、すべてのデータを一度に挿入する必要があります。それでも、SELECT操作の効率向上は価値があるかもしれません。明らかに、ユーザーがデータを要求する頻度に基づいて、テーブルを縦に分割した方が良いでしょう。おそらくこれが私がすべきことのすべてです。私は質問をする際に、これを行うことが価値があることの確認を探していると思います。
編集2:
データの使用:通常、問題のあるアイテムのみに焦点を合わせるため、データの大部分は見られたり必要とされたりすることはありません。しかし、問題を見つけようとする際には、さまざまなツールを使用してデータを検索し、拡大するアイテムを決定します。
たとえば、メモリ使用量の値(顧客固有の独自のソフトウェアプログラム)と再起動/クラッシュの間に相関関係があることがわかりました。収集したデータポイントの1つはこのメモリ使用量に関連しており、特定のメモリ使用量を超えた後にデバイスが不安定になることを示す履歴データを見ることができました。今日、このソフトウェアを実行しているデバイスのサブセットについて、この値を確認し、値が高すぎる場合は再起動コマンドを発行します。これが発見されるまで、このデータの収集は価値があるとは思いませんでした。
このため、値に疑問がある場合でも、約100個のデータポイントを収集して保存することを維持しています。しかし、通常の日常的な使用では、ユーザーは通常、これらのパラメーターを十数個検討します。ユーザーが特定の地理的領域に興味を持つようになると、(ソフトウェアを使用して)おそらく数十個のセンサーのデータのグラフまたはスプレッドシートを生成できます。温度、気圧、光レベルなどを示す2つまたは3つのプロット線で30日間のグラフを見るのは珍しいことではありません。これを行うと、次のようなクエリが実行されます。
SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);
(各センサーに独自のテーブルがある元のMySQLバージョンでは、3つの個別のクエリが発行されますが、結果はソフトウェアで結合されてグラフを作成します。)
data
テーブルには非常に多くの行(〜1000万)が含まれているため、インデックスがid
およびdata_timestamp
になっているにもかかわらず、パフォーマンスは複数テーブルシナリオよりも著しく劣っています(この例では1秒未満ではなく、9秒で4500行が返されます)。特定の条件を満たすセンサーを見つける機能は、複数テーブルスキーマでは実質的にゼロであるため、単一のテーブルに移行する理由です。
このタイプのクエリは、複数のユーザーが異なるデータグループを選択し、各結果のグラフを比較するため、すぐに連続して実行できます。グラフまたはスプレッドシートごとに10秒近く待機するのは非常にイライラする可能性があります。
データは90日後に破棄されます。アーカイブできますが、現在は要件ではありません。
この情報が、収集と保存後のデータの使用方法をより適切に示すのに役立つことを願っています。