0

センサー、読み取り値、および読み取り値が取得されたタイムスタンプを示す測定値のデータベースがあります。測定値は、変更がある場合にのみ記録されます。各センサーが特定の測定値を読み取っている範囲を示す結果セットを生成したいと考えています。

タイムスタンプはミリ秒単位ですが、結果を秒単位で出力しています。

ここにテーブルがあります:

CREATE TABLE `raw_metric` (
    `row_id` BIGINT NOT NULL AUTO_INCREMENT,
    `sensor_id` BINARY(6) NOT NULL,
    `timestamp` BIGINT NOT NULL,
    `angle` FLOAT NOT NULL,
    PRIMARY KEY (`row_id`)
)

現在、サブクエリを使用して必要な結果を取得していますが、データポイントが多いとかなり遅くなります。

SELECT row_id,
    HEX(sensor_id),
    angle,
    (
        COALESCE((
                SELECT MIN(`timestamp`)
                FROM raw_metric AS rm2
                WHERE rm2.`timestamp` > rm1.`timestamp`
                    AND rm2.sensor_id = rm1.sensor_id
                ), UNIX_TIMESTAMP() * 1000) - `timestamp`
        ) / 1000 AS duration
FROM raw_metric AS rm1

基本的に、範囲を取得するには、次の読み取り値を取得する必要があります (または、別の読み取り値がない場合は現在の時刻を使用します)。サブクエリは、現在のタイムスタンプよりも遅いが同じセンサーからの最小タイムスタンプを見つけます。

このクエリは頻繁には発生しないため、タイムスタンプ列にインデックスを追加して挿入を遅くする必要はありません。これを行う別の方法について誰かが提案してくれることを望んでいました。

更新: row_idはタイムスタンプと共にインクリメントする必要がありますが、ネットワーク遅延の問題により保証できません。そのため、可能性は低いですが、より低い row_id を持つエントリが後の row_id の後に発生する可能性があります。

4

3 に答える 3

1

これはおそらく解決策というよりもコメントとして適切ですが、コメントとしては長すぎます。

lead()関数を MySQLに実装しようとしていますが、残念ながら MySQL にはウィンドウ関数がありません。Oracle、DB2、Postgres、SQL Server 2012 に切り替えて、組み込みの (および最適化された) 機能を使用できます。わかりました、それは現実的ではないかもしれません。

したがって、データ構造を考えると、相関サブクエリまたは非等価結合 (実際には、一致があるため、部分等価結合) のいずれかを実行する必要がありますsensor_id。インデックスを追加しない限り、これらは高価な操作になります。1 秒間に何十回も測定値を追加しない限り、インデックスの追加のオーバーヘッドは大した問題にはなりません。

データ構造を変更することもできます。読み取り値を列挙する連番である「センサーカウンター」がある場合は、これを等結合として使用できます (ただし、パフォーマンスを向上させるにはインデックスが必要な場合があります)。これをテーブルに追加するには、トリガーが必要です。これは、挿入時のインデックスよりもパフォーマンスが低下する可能性があります。

少数のセンサーしかない場合は、センサーごとに個別のテーブルを作成できます。ああ、私はこの提案にうめき声を感じることができます. しかし、そうすると、自動インクリメント ID が同じ役割を果たします。正直なところ、両手のセンサーの数を数えることができる場合にのみ、これを行います。

最後に、挿入中にヒットを取得し、各レコードに「有効な」時間と「終了」時間 (およびセンサー ID とタイムスタンプまたは ID のいずれかのインデックス) を含めることをお勧めします。これらの追加の列を使用すると、おそらく、テーブルのより多くの用途を見つけるでしょう。

1 つのセンサーに対してのみこれを行う場合は、情報用の一時テーブルを作成し、自動インクリメントされた ID 列を使用します。次に、データを挿入します。

insert into temp_rawmetric (orig_row_id, sensor_id, timestamp, angle)
    select orig_row_id, sensor_id, timestamp, angle
    from raw_metric
    order by sensor_id, timestamp;

temp_rawmetric_idテーブルに、自動インクリメントされる列と主キー (自動的にインデックスを作成する) があることを確認してください。はorder by、タイムスタンプに従ってこれがインクリメントされるようにします。

次に、次のようにクエリを実行できます。

select trm.sensor_id, trm.angle,
       trm.timestamp as startTime, trmnext.timestamp as endTime
from temp_rawmetric trm left outer join
     temp_rawmetric trmnext
     on trmnext.temp_rawmetric_id = trm.temp_rawmetric_id+1;

これには、データを追加するために元のデータをパススルーしてから、一時テーブルで主キーを結合する必要があります。最初は時間がかかるかもしれません。2番目はかなり速いはずです。

于 2013-05-08T17:59:34.307 に答える