0

大量のgpsデータといくつかの追加情報をデータベースに保存し、レポートやその他の頻繁ではないタスクのためにそれにアクセスするタスクがあります。

GPSデバイスからメッセージを受信すると、フィールドの数が変化する可能性があります。例えば

メッセージ1:DeviceId LatLonスピードコース
DIO1ADC1メッセージ2:DeviceIdLatコースDIO2IsAlarmOn
メッセージ3:DeviceId LatLon高さコースDIO2IsAlarmOnなど最大20〜30フィールド

さまざまなデバイスベンダー、さまざまなプロトコルなど、フィールドの数を統一する方法はありません。また、データベースのサイズと、できるだけ多くのdbベンダーをサポートする必要があるという問題もあります(NHibernateが使用されます)。

だから私はそのようにメッセージを保存することを思いついた:
Table1-Tracks
PK-TrackId
TrackStartTime
TrackEndTime
FirstMessageIndex(stores MessageId)
LastMessageIndex(stores MessageId)
DeviceId(FKではない)

表2-メッセージ
PK-MessageIdTimeStampFirstDataIndex (stores
DataId

LastDataIndex(stores DataId)

表3-MessageDataPK
-DataIddouble
Data
short DataType

すべてのインデックスはhiloで割り当てられます。Nhibernateが3000+kメッセージの認証を迅速に処理できるようにクエリを調整しました(バッハも使用されます)。パフォーマンスATMに満足しています。しかし、50GB以上または100GB以上のサイズでどのように機能するかはわかりません。

私の問題とストレージ設計全体に関するヒントやヒントに非常に感謝します=)
ありがとう、Alexey
PS。私の英語をお詫びします=)

4

3 に答える 3

3

簡単に言えば、アプリケーション、特にGPS デバイスから受信したメッセージの異種構造は、設計をEAV データストア構造にプッシュします(エンティティは Message 、属性は "MessageData.DataType" で、値は体系的にダブル。)

質問で概説した3つのテーブルの設計は、特定のメッセージのすべてのデータポイントが連続して番号付けされることにより、MessageDataが格納される方法に暗黙的なシーケンスがあるという意味で、従来のEAV実装から少し離れているようです(メッセージからそのデータポイントへのリンクは、範囲内の DataId によって駆動されます。
それは悪い考えです!これには多くの問題があります。注目すべきは、メッセージの挿入に不要なボトルネックが発生することです。前のメッセージのすべてのデータポイントまで、2 番目のメッセージの挿入を開始できません。もう 1 つの問題は、メッセージとデータポイントの関係のインデックス作成が困難になることです (基礎となる DBMS では効率的ではありません)。
==> 提案:MessageId は MessageDataテーブルの外部キーです。(そして、たとえばメンテナンス目的で、複合キーを使用してこのテーブルの特定のレコードを参照する必要があるという犠牲を払って、スペースを節約するために、MessageData テーブルの DataId PK を完全に削除する可能性があります)

もう 1 つの提案は、最も一般的な属性 (データポイント) を Message テーブルのレベルに格納することです。たとえば、緯度と経度だけでなく、コースや一部のアラームなども含まれます。この情報をメッセージに正しく含める理由は、データへのクエリを最適化するためです (MessageData テーブルで必要な自己結合の数を制限します)。

Messages テーブルと MessageData テーブルの両方にメッセージの一部が含まれていない可能性があるため、後者の MessageDetail テーブルまたはそのような名前の名前を変更することもできます。

最後に、これらの double 型以外のデータ値を許可することをお勧めします。一部のアラートは単にブール値などであると予想されます。さまざまな種類のデータポイント (短いエラー メッセージ文字列など) を受け入れることを許可する以外に、これにより、データポイントを複数の「詳細」テーブルに分割する機会が得られる場合もあります。 double 用、boolean 用、string 用など。この方法では、クエリの生成方法にこれらの詳細の一部を組み込む必要があるという意味でスキーマが複雑になりますが、パフォーマンス/スケーリングの可能性を提供できます。ます。

于 2009-10-23T16:19:13.167 に答える
0

私は同様のアプリケーションを書いています。ベンダーからのすべての可能な値を認識し、必要なすべてのフィールドを含む適切なスキーマを作成することをお勧めします。これにより、パフォーマンスの高い/最も単純なレポート クエリを作成できます。

さらに、指定された (長さの) データを含むフィールドを作成できるため、場所を節約し、パフォーマンスを向上させることができます。

既知の値を持つ 1 つのベンダーがあるため、このために 1 つのテーブルを作成しました。このテーブルは、ネイティブの MS SQL Server メカニズムによって簡単に分割できます。

したがって、私の最も単純な状況では、1 つのストアド プロシージャを記述してデータを保存することができます。NHibernate はなく、純粋な ICommand だけです。

アプリケーションの残りの部分は NHibernate を使用します。

于 2009-12-27T22:51:23.450 に答える
0

コメントの長さが固定されているため、応答でどのように機能するかをより詳細に説明しようとします =) 受信シーケンスは次
のとおりです。
2. 次に、個別のデバイス ID を絞り込みます。
3. デバイス ID ごとに、次の構造を持つ MS EntLib 分離ストレージ キャッシュを使用します
。DeviceId --> List DeviceId はルックアップ キーです。 4.キャッシュに 1,000 件
を超えるメッセージがある場合 - それらを一度に db に書き込み、その後、「index」をルックアップ テーブルに書き込みます。
Index: id
serial_id
index_start_datetime
index_end_datetime
index_first_dataid
index_last_dataid

また、データをカップルで保存します: id data1 data2 タイプ
(緯度経度、スピードコース、adc1 adc2、dio1、dio2 など)、およびカップルされた値がない場合: 値 0

double を選択したのは、デバイスが送信するあらゆるタイプのデータを保存できるからです。文字列を送信しませんが、ほとんどの em は 1,0,23,50.0000N30.00000,1,2,12,0,1,2 などの csv スタイルです。アラームなどでも同じタイプのデータがあります。データを取得する必要がある場合は、指定された日時ウィンドウと DeviceId のインデックスを見つけて、開始時刻と終了時刻を知っている実際のデータを取得します。また、複雑なクエリはありません。シンプルに2つだけ。他のコードは、いくつかのプロトコル「マッピング」を使用してこれを解釈しています。EAVのヒントをありがとう。よく合っていると思います。最初のテーブル Track は、メッセージを集約し、以前に説明した検索アルゴリズムでそれらをすばやく取得するためのものです。

于 2009-10-23T20:39:20.307 に答える