データベースの再設計の機会:このセンサーデータ収集に使用するテーブル設計は?


13

バックグラウンド

約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日後に破棄されます。アーカイブできますが、現在は要件ではありません。

この情報が、収集と保存後のデータの使用方法をより適切に示すのに役立つことを願っています。


この質問が正しい答えを得るには、おそらくデータが実際にどのように使用されているかを拡張する必要があります。あなたはこれまでに提供した情報の深さの曲線に先んじていますが、間違った角度から質問をしているかもしれません。
マークストーリースミス

良い点、@ Mark、私もそれについて詳しく説明します。私はそれが圧倒されることを恐れて長すぎる質問をしないようにしようとしていた。
-JYelton

回答:


5

大きな理由で、テーブルのパーティション分割を検討する必要があります。

巨大なテーブルにあるすべてのインデックスは、たとえ1つのインデックスであっても、INSERT、UPDATE、およびDELETEを実行するときにインデックスメンテナンスを実行するためだけに大量のCPU負荷とディスクI / Oを生成する可能性があります。

2011年10月7日に、テーブルパーティション分割が大きな助けになる理由について以前の投稿を書きました。これは私の過去の投稿からの抜粋です。

データのパーティション化は、同じクラスに論理的かつまとまりのあるデータをグループ化するのに役立ちます。データが正しくグループ化されている限り、各パーティションを検索するパフォーマンスを主に考慮する必要はありません。論理パーティションを作成したら、検索時間に集中してください。IDのみでデータを分離しているだけの場合、読み取りまたは書き込みのために多くのデータ行にアクセスできない可能性があります。さて、それは主要な考慮事項であるはずです:最も頻繁にアクセスされるすべてのIDを見つけ、それによってパーティション分割します。アクセス頻度の低いすべてのIDは、「ブルームーンに1回」クエリのインデックスルックアップによって引き続きアクセス可能な1つの大きなアーカイブテーブルに存在する必要があります。

これについては、私の投稿全体を後で読むことができます。

追いかけるために、10GBテーブルでめったに使用されないデータを調査して見つける必要があります。そのデータは、履歴的な性質のためにアドホッククエリが必要な場合にすぐにアクセスできるアーカイブテーブルに配置する必要があります。そのアーカイブを10GBから移行してからOPTIMIZE TABLE10GBテーブルに移行すると、ワーキングセットがSELECT、INSERT、UPDATE、およびDELETEを実行するのにより高速になる可能性があります。DDLでさえ、10GBのテーブルよりも2GBのワーキングセットの方が速くなります。

更新2012-02-24 16:19 EDT

考慮すべき2つのポイント

  1. コメントから、正規化が必要な場合があるようです。
  2. 90日以上経過したものすべてをアーカイブテーブルに移行する必要がある場合がありますが、アーカイブとワーキングセットには同時にアクセスする必要があります。データがすべてMyISAMの場合、MERGEストレージエンジンの使用をお勧めします。最初に、ワーキングセットMyISAMテーブルとアーカイブMyISAMテーブルを結合するMERGEテーブルマップを作成します。1つのMyISAMテーブルに91日未満のデータを保持し、90日以上前のデータをアーカイブにロールオーバーします。MERGEテーブルマップのみを照会します。

以下に、使用方法に関する2つの投稿を示します。

これは、私が多くの列を持つテーブルに追加した投稿です

MySQLの列が多すぎる


それほど頻繁に必要ではない列もありますが、すべてのセンサーはほぼ同じ割合の注意を引きます。したがって、テーブルを垂直に分割することは有利だと想像できます。たとえば、20列のテーブル(頻繁にアクセスされる)と80列のテーブル(頻繁にアクセスされない)。これがパーティション分割と同じかどうかはわかりません。
-JYelton

編集してくれてありがとう。「MySQLの列が多すぎます」に関する投稿を読みました。役に立つかもしれないいくつかの追加のポイントで質問を編集します。
JYelton

5

興味深い...すべてのセンサーが同じ種類のデータを生成する場合、それらをすべて同じテーブルに置くことは理にかなっていますが、その量のデータを使用すると、パフォーマンスが心配される理由がわかります。

90日間はグラフを作成する通常の時間ですか?その場合、2つのテーブルを作成できます。90日前(または多少余裕がある場合はもう少し)データを保存するメインセンサーデータテーブルと、それより古いものはすべてアーカイブテーブルに格納されます。これにより、レポートの生成を開始するテーブルのサイズを小さくすることができます。また、10 GBのデータの大部分がメインテーブルではなくアーカイブテーブルにあることを願っています。アーカイブジョブは、夜間に実行するようにスケジュールできます。

また、レポートの生成に適した構造でデータを保存する別のレポートデータベースを構築することを検討することもできます(クエリの対象とより厳密に一致するように設計されたテーブル。 (可能であれば)生成し、定期的に(夜間など)メインデータベースから再入力します。もちろん、最新のデータから生成されたレポートが必要な場合、これはうまく機能しない可能性があります。


この時点で90日を過ぎたものを保存する必要はありませんが、良いでしょう。「アーカイブ」テーブルに保存することをお勧めします。グラフとデータ分析の範囲は、わずか数時間から90日間です。ほとんどのグラフ作成リクエストでは、過去1週間程度のデータのみが使用されますが、90日間のグラフが一般的です。当社は(まだ)より長いレポートを要求していません。
-JYelton

@JYelton:このアプローチでは、必要な数のティアを設定できます。最新のテーブルは、今日からのみ取得できます。次の表は、今日から2週間前までのものです。次の表は、今日から90日前までのものです。最後のテーブルはすべてでした。
FrustratedWithFormsDesigner

私があなたを正しく理解しているなら、あなたはテーブルを複製するように言っていますが、異なる期間のカバレッジで。したがって、誰かが7日間のレポートを要求した場合、1週間だけ遡るテーブルが使用されます。その後、8日間に拡張すると、次に大きいテーブル(30日間など)が使用されますか?これは確かに短期間のクエリの速度を改善しますが、ストレージ(安い)と階層化テーブルを処理するためのプログラミングロジック(それほど安くはありません)を犠牲にします。
-JYelton

@JYelton:はい、あなたはそれを正しく理解していると思います。クエリの期間の範囲が標準の場合(今日-1日、今日-7日、今日-30日、今日-90日)、どのテーブルを使用するかを常に知っているので、それほど難しいとは思わないヒット。範囲の開始が現在の日付ではない可能性がある時間範囲の長さが可変である場合、実装するロジックが複雑になり、複数のテーブルのUNION操作でテーブルをまたぐクエリが高価になる可能性があります。
FrustratedWithFormsDesigner
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.