web-dev-qa-db-ja.com

Influxで、特定のキーの最新のタイムスタンプ(MAX /最後)をクエリする

InfluxDB(v1.1)を使用して、特定のキーの最後のエントリのタイムスタンプを取得する必要があります。これが保存されている測定値に関係なく、これがどの値であったかに関係なく。

セットアップは簡単で、3つの測定値があります:locationnetworkおよびusage
キーは1つだけです:device_id

疑似コードでは、これは次のようになります。

# notice the lack of a FROM clause on measurement here...
SELECT MAX(time) WHERE 'device_id' = 'x';

質問:これを照会する最も効率的な方法は何でしょうか?

これが必要な理由は、分散型の同期プロセスがあるためです。過去1時間に更新されたデバイスと、数か月更新されていないデバイスがあります。デバイス(キー)の明確な「最終更新日」タイムスタンプを取得できると、Influxへの新しいポイントをより効率的に保存できます。

InfluxDBのGitHubリポジトリ(#5793) についても同様の議論があることに気づきましたが、質問はフィールド/キーによるフィルタリングではありません。そして、これがまさに私が欲しいものです。特定のキーの「最後の」エントリを取得します。

9
Juliën

残念ながら、あなたが探しているものを取得する単一のクエリはありません。クライアント側で少し作業を行う必要があります。

必要なクエリは

SELECT last(<field name>), time FROM <measurement> WHERE device_id = 'x'

測定ごとにこのクエリを実行する必要があります。

SELECT last(<field name>), time FROM location WHERE device_id = 'x'
SELECT last(<field name>), time FROM network WHERE device_id = 'x'
SELECT last(<field name>), time FROM usage WHERE device_id = 'x'

そこから、タイムスタンプが最大のものを取得します

> select last(value), time from location where device_id = 'x'; select last(value), time from network where device_id = 'x'; select last(value),     time from usage where device_id = 'x';
name: location
time                last
----                ----
1483640697584904775 3

name: network
time                last
----                ----
1483640714335794796 4

name: usage
time                last
----                ----
1483640783941353064 4
9
Michael Desa

私はこれを試しました、そしてそれは私のために単一のコマンドでうまくいきました:

SELECT last(<field name>), time FROM location, network, usage WHERE device_id = 'x'

私が得た結果:

name: location
time                last
----                ----
1483640697584904775 3

name: network
time                last
----                ----
1483640714335794796 4

name: usage
time                last
----                ----
1483640783941353064 4
6
JasonG-FR

tl; dr;first()およびlast()測定に複数のフィールドがあり、フィールドにNULL値がある場合、セレクターは一貫して機能しません。最も効率的なソリューションは、これらのクエリを使用することです

最初:

SELECT * FROM <measurement> [WHERE <tag>=value] LIMIT 1

最終:

SELECT * FROM <measurement> [WHERE <tag>=value] ORDER BY time DESC LIMIT 1

説明:

測定に単一のフィールドがある場合、推奨される解決策が機能しますが、複数のフィールドがあり、値がNULLになる可能性がある場合、first() およびlast()セレクターが勝ちました一貫して機能せず、フィールドごとに異なるタイムスタンプを返す場合があります。たとえば、次のデータセットがあるとします。

time                   fieldKey_1     fieldKey_2     device
------------------------------------------------------------
2019-09-16T00:00:01Z   NULL           A              1
2019-09-16T00:00:02Z   X              B              1
2019-09-16T00:00:03Z   Y              C              2
2019-09-16T00:00:04Z   Z              NULL           2

この場合、クエリ

SELECT first(fieldKey_1) FROM <measurement> WHERE device = "1" 

戻ります

time                   fieldKey_1
---------------------------------
2019-09-16T00:00:02Z   X         

そして、first(fieldKey_2)の同じクエリは異なる時間を返します

time                   fieldKey_2
---------------------------------
2019-09-16T00:00:01Z   A

lastでクエリを実行すると、同様の問題が発生します。

疑問に思っている場合は、次のような結果で「Epoch-0」の時間を取得するため、「first(*)」のクエリは実行されません。

 time                   first_fieldKey_1    first_fieldKey_2
 -------------------------------------------------------------
 1970-01-01T00:00:00Z   X                   A

したがって、ソリューションは [〜#〜] limit [〜#〜]ORDER BY の組み合わせを使用してクエリを実行することになります。たとえば、初めて使用できる値は次のとおりです。

SELECT * FROM <measurement> [WHERE <tag>=value] LIMIT 1

そして最後のものはあなたが使うことができます

SELECT * FROM <measurement> [WHERE <tag>=value] ORDER BY time DESC LIMIT 1

インデックスを中継するため、安全で高速です。

このより単純なアプローチは 開始ポストにリンクされたスレッド で言及されていたが、破棄されたことを言及するのは興味深いことです。見落とされただけかもしれません。

ここでは、件名について InfluxDataブログのスレッド もあり、このアプローチの使用を提案しています。

1