查询 InfluxDB 最后一点
Query InfluxDB last point
我使用 c++ 库 influxdb-cxx,它使用 curl 将数据插入数据库。
在我的 C++ 程序中,我将编写 4 个测量值,每个测量值每秒都有几十个要插入的点。
我使用UDP发送数据
sensor_->influxdb_ = influxdb::InfluxDBFactory::Get("udp://localhost:8089?db=udp");
其中一个插入的c++代码看起来:
sensor_->influxdb_->write(influxdb::Point("/controller/data")
.addField("angular", sensor_->angular())
.addField("speed_left_rear", sensor_->speedl()
.addField("speed_right_rear", sensor_->speedr()
.addField("voltage", sensor_->voltage()));
它将插入一个测量点“/controller/data”。这个点有四个字段,没有标签。
查询数据库中最后半秒的数据时出现问题。我打开一个终端并输入
influx
use udp
create retention policy "1h" on udp duration 1h replication 1 shard duration 1h default
precision rfc3339
SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
预期行为:
最后半秒能拿分,所有字段都不为空,同一行的数据有相同的时间戳。
实际行为:
有时提交的值为空。
例如:
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
2021-08-02T08:47:41.17175053Z 99 0 0 23152
2021-08-02T08:47:41.189857794Z -49 0 0 23152
2021-08-02T08:47:41.203743539Z 282 0 0 23152
2021-08-02T08:47:41.219689002Z 299 0 0 23152
2021-08-02T08:47:41.235739755Z 249 0 0 23223
2021-08-02T08:47:41.251701843Z 299 0 0 23311
2021-08-02T08:47:41.267655473Z 133 0 0 23311
2021-08-02T08:47:41.284691461Z 382 0 0 23311
2021-08-02T08:47:41.299605898Z 116 0 0 23240
2021-08-02T08:47:41.315760775Z 23240
2021-08-02T08:47:41.331771862Z 23240
2021-08-02T08:47:41.347798407Z 23240
2021-08-02T08:47:41.363746204Z 23364
2021-08-02T08:47:41.380132952Z 23364
2021-08-02T08:47:41.395660171Z 23364
2021-08-02T08:47:41.411623426Z 23364
2021-08-02T08:47:41.427676221Z 23241
2021-08-02T08:47:41.443633642Z 23241
2021-08-02T08:47:41.459634521Z 23241
2021-08-02T08:47:41.475580859Z 23241
2021-08-02T08:47:41.491627529Z 23400
2021-08-02T08:47:41.507684407Z 23400
2021-08-02T08:47:41.523670412Z 23400
2021-08-02T08:47:41.539542668Z 23400
2021-08-02T08:47:41.556554739Z 23400
2021-08-02T08:47:41.571867004Z 23329
2021-08-02T08:47:41.587669261Z 23329
2021-08-02T08:47:41.603685306Z 23329
2021-08-02T08:47:41.619762893Z 23329
2021-08-02T08:47:41.636273305Z 23293
2021-08-02T08:47:41.651680944Z 23293
2021-08-02T08:47:41.667774571Z 23293
2021-08-02T08:47:41.683901448Z 23293
2021-08-02T08:47:41.699780996Z 23417
2021-08-02T08:47:41.715881623Z 23417
2021-08-02T08:47:41.732012Z 23417
2021-08-02T08:47:41.747715092Z 23417
2021-08-02T08:47:41.763705763Z 23205
2021-08-02T08:47:41.779796182Z 23205
2021-08-02T08:47:41.795692354Z 23205
和
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
2021-08-02T08:49:30.314298081Z 649 0 0 23293
2021-08-02T08:49:30.330174725Z 316 0 0 23293
2021-08-02T08:49:30.346282365Z 798 0 0 23187
2021-08-02T08:49:30.362351798Z 732 0 0 23187
2021-08-02T08:49:30.378310691Z 282 0 0 23187
2021-08-02T08:49:30.39422Z 549 0 0 23293
2021-08-02T08:49:30.410205143Z 615 0 0 23329
2021-08-02T08:49:30.42628595Z 149 0 0 23329
2021-08-02T08:49:30.442316883Z 282 0 0 23329
2021-08-02T08:49:30.45822561Z 582 0 0 23329
2021-08-02T08:49:30.474172836Z 133 0 0 23364
2021-08-02T08:49:30.490214269Z 233 0 0 23364
2021-08-02T08:49:30.506210203Z 549 0 0 23364
2021-08-02T08:49:30.522200303Z -399 0 0 23364
2021-08-02T08:49:30.538234736Z -366 0 0 23364
2021-08-02T08:49:30.554288127Z 0 23364
2021-08-02T08:49:30.570351727Z 0 23364
2021-08-02T08:49:30.586195413Z 0 23364
2021-08-02T08:49:30.602191055Z 0 23241
2021-08-02T08:49:30.618195155Z 0 23241
2021-08-02T08:49:30.634950578Z 0 23241
2021-08-02T08:49:30.650237772Z 0 23223
2021-08-02T08:49:30.666386828Z 0 23276
2021-08-02T08:49:30.682325013Z 0 23276
2021-08-02T08:49:30.698237823Z 0 23276
2021-08-02T08:49:30.714291797Z 0 23276
2021-08-02T08:49:30.730265564Z 0 23099
2021-08-02T08:49:30.746241957Z 0 23099
2021-08-02T08:49:30.762230307Z 0 23099
2021-08-02T08:49:30.778286615Z 0 23099
2021-08-02T08:49:30.794283132Z 0 22993
2021-08-02T08:49:30.819896051Z 0 23134
2021-08-02T08:49:30.826242917Z 0 23134
2021-08-02T08:49:30.84235989Z 0 23134
2021-08-02T08:49:30.86443611Z 0 23134
2021-08-02T08:49:30.874357007Z 0 23170
2021-08-02T08:49:30.890441315Z 0 23170
2021-08-02T08:49:30.906395249Z 0 23170
2021-08-02T08:49:30.922352392Z 0 23170
2021-08-02T08:49:30.942798927Z 0 23187
2021-08-02T08:49:30.954241427Z 0 23187
2021-08-02T08:49:30.970329818Z 0 23187
2021-08-02T08:49:30.986202379Z 0 23240
2021-08-02T08:49:31.002118397Z 0 23046
2021-08-02T08:49:31.018028873Z 0 23046
2021-08-02T08:49:31.034310053Z 0 23046
如您所见,有很多空值。
左列更有可能为空,最右列的字段键 voltage
永远不会有空值。
所以我猜想:同一行的filed value对应同一个时间戳,但不是同时写入数据库,可能有的写入了,有的没有写入。是吗?
有没有办法让同一个raw中的不同字段同时写入?所以我查询的时候同一行的每个字段都不为null。
或者怎么查询最近的所有字段都不为null的点?其实我想查询的是测量中的最后一个点:select * from "udp".."/controller/data" order by time desc limit 1
,但是它有时 returns 一些字段具有空值的点。
而且我发现 last()
对我的问题没有帮助。
因为如果我使用 SELECT last(*) FROM "udp".."/controller" WHERE time > now() - 1s
(我使用 WHERE
子句因为我认为它可以通过指定时间范围让它查询得更快),它只是合并 last(angular)
、[=25= 的结果], last(speed_right_rear)
, last(voltage)
成一分。但是字段值可能不对应相同的时间戳。
环境信息:
我运行所有这些程序都在类似于raspberryPi的嵌入设备nanopi上。
- 系统信息:Linux 4.4.179 aarch64
- InfluxDB 版本:1.8.7
配置:
我的 influx.conf
[[udp]]
enabled = true
batch-size = 50
batch-pending = 5
batch-timeout = "1s"
并且我尝试修改 UDP 批量大小以查看它是否有任何不同:
如果我在influxdb.conf
中修改batch-size为1
[[udp]]
enabled = true
batch-size = 1
batch-pending = 5
batch-timeout = "1s"
会增加很多CPU负载,我只能获取时间>现在-22s
的点
select * from "udp".."/controller/data" where time >= now() - 22s
它 returns 结果如下:
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 21s
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
1627894525069581596 599 0 0 23276
1627894525115397757 366 0 0 23116
1627894525147390263 782 0 0 23258
1627894525163375140 216 0 0 23258
1627894525179457142 449 0 0 23258
1627894525211368273 249 0 0 23382
1627894525227548857 532 0 0 23382
1627894525259374239 133 0 0 23382
1627894525275378367 249 0 0 23169
1627894525307387789 665 0 0 23169
1627894525323413499 499 0 0 23169
1627894525355366338 599 0 0 23311
1627894525371388841 382 0 0 23311
1627894525387508467 499 0 0 23311
1627894525403456887 1148 0 0 23223
1627894525420205921 549 0 0 23205
1627894525436119925 149 0 0 23205
1627894525452726045 366 0 0 23205
1627894525468630132 183 0 0 23223
1627894525484748008 -99 0 0 23223
1627894525500814260 249 0 0 23223
1627894525516629098 499 0 0 23223
1627894525533157344 848 0 0 23205
1627894525548644353 366 0 0 23205
1627894525564793437 16 0 0 23205
1627894525627496298 66 0 0 23347
1627894525675488264 83 0 0 23240
1627894525723471189 -33 0 0 23418
1627894525755489652 166 0 0 23418
1627894525772796929 332 0 0 23418
1627894525803355328 23152
有时它仍然是 returns 空值。
所以改batch size对这个问题不起作用,batch-size好像是属性一列,把一定量的列数据打包,然后写入数据库。
我不会使用 InfluxDB 处理最近 500 毫秒的数据。该软件不适用于此类解决方案。 InfluxDB 没有优先将所有值放在定义的时间。它不是实时系统。如果您需要类似的东西,我建议您使用实时 PLC 类型的设备。
但是......如果你想以这种方式使用它,我可以建议以下棘手的解决方案:
- 请求不更新的数据,例如 400ms:
SELECT last(*) FROM "udp".."/controller/data" WHERE time >= now() - 10s and time<=now()-400ms
假设在 400 毫秒后您在所有字段中都有值。
3)请求安全延迟的数据,例如500ms:
SELECT first(*) FROM "udp".."/controller/data" WHERE time >= now() - 500ms
上面的查询应该会在 500 毫秒后为您提供第一个值。假设需要不到 500 毫秒的时间来写入所有字段值。
- 使用 where 子句为所有值字段请求数据,如果那里只有数据,它将始终为真:
SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 5s and "angular">-9999999 and "speed_left_rear">-9999999 and "speed_right_rear">-9999999"> and "voltage">-9999999 limit 1
以上所有假设您无法读取低于 -9999999 的值。
这样,您应该只收到所有值都已写入且不早于 5s 的系列。您将获得的值是与所有写入值具有相同时间戳的最新值。
和 2) 解决方案在某些条件下可能会工作或不工作,假设有延迟(这取决于系统工作负载等)。 3) 如果您需要所有具有相同时间戳的值,这可能是最佳解决方案。
另一种方法是进行 4 个独立查询,在其中查询最后一个值:
SELECT last(angular) FROM "udp".."/controller/data"
SELECT last(speed_left_rear) FROM "udp".."/controller/data"
SELECT last(speed_right_rear) FROM "udp".."/controller/data"
SELECT last(voltage) FROM "udp".."/controller/data"
- 甚至在子查询中请求它:
Select * from (SELECT last(angular) as "angular" FROM "udp".."/controller/data"),(SELECT last(speed_left_rear) as "speed_left_rear" FROM "udp".."/controller/data"),(SELECT last(speed_right_rear) as "speed_right_rear" FROM "udp".."/controller/data"),(SELECT last(voltage) as "voltage" FROM "udp".."/controller/data")
它会给你最新的值,但它们可能没有相同的时间戳。
我使用 c++ 库 influxdb-cxx,它使用 curl 将数据插入数据库。 在我的 C++ 程序中,我将编写 4 个测量值,每个测量值每秒都有几十个要插入的点。 我使用UDP发送数据
sensor_->influxdb_ = influxdb::InfluxDBFactory::Get("udp://localhost:8089?db=udp");
其中一个插入的c++代码看起来:
sensor_->influxdb_->write(influxdb::Point("/controller/data")
.addField("angular", sensor_->angular())
.addField("speed_left_rear", sensor_->speedl()
.addField("speed_right_rear", sensor_->speedr()
.addField("voltage", sensor_->voltage()));
它将插入一个测量点“/controller/data”。这个点有四个字段,没有标签。
查询数据库中最后半秒的数据时出现问题。我打开一个终端并输入
influx
use udp
create retention policy "1h" on udp duration 1h replication 1 shard duration 1h default
precision rfc3339
SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
预期行为: 最后半秒能拿分,所有字段都不为空,同一行的数据有相同的时间戳。 实际行为: 有时提交的值为空。 例如:
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
2021-08-02T08:47:41.17175053Z 99 0 0 23152
2021-08-02T08:47:41.189857794Z -49 0 0 23152
2021-08-02T08:47:41.203743539Z 282 0 0 23152
2021-08-02T08:47:41.219689002Z 299 0 0 23152
2021-08-02T08:47:41.235739755Z 249 0 0 23223
2021-08-02T08:47:41.251701843Z 299 0 0 23311
2021-08-02T08:47:41.267655473Z 133 0 0 23311
2021-08-02T08:47:41.284691461Z 382 0 0 23311
2021-08-02T08:47:41.299605898Z 116 0 0 23240
2021-08-02T08:47:41.315760775Z 23240
2021-08-02T08:47:41.331771862Z 23240
2021-08-02T08:47:41.347798407Z 23240
2021-08-02T08:47:41.363746204Z 23364
2021-08-02T08:47:41.380132952Z 23364
2021-08-02T08:47:41.395660171Z 23364
2021-08-02T08:47:41.411623426Z 23364
2021-08-02T08:47:41.427676221Z 23241
2021-08-02T08:47:41.443633642Z 23241
2021-08-02T08:47:41.459634521Z 23241
2021-08-02T08:47:41.475580859Z 23241
2021-08-02T08:47:41.491627529Z 23400
2021-08-02T08:47:41.507684407Z 23400
2021-08-02T08:47:41.523670412Z 23400
2021-08-02T08:47:41.539542668Z 23400
2021-08-02T08:47:41.556554739Z 23400
2021-08-02T08:47:41.571867004Z 23329
2021-08-02T08:47:41.587669261Z 23329
2021-08-02T08:47:41.603685306Z 23329
2021-08-02T08:47:41.619762893Z 23329
2021-08-02T08:47:41.636273305Z 23293
2021-08-02T08:47:41.651680944Z 23293
2021-08-02T08:47:41.667774571Z 23293
2021-08-02T08:47:41.683901448Z 23293
2021-08-02T08:47:41.699780996Z 23417
2021-08-02T08:47:41.715881623Z 23417
2021-08-02T08:47:41.732012Z 23417
2021-08-02T08:47:41.747715092Z 23417
2021-08-02T08:47:41.763705763Z 23205
2021-08-02T08:47:41.779796182Z 23205
2021-08-02T08:47:41.795692354Z 23205
和
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 500ms
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
2021-08-02T08:49:30.314298081Z 649 0 0 23293
2021-08-02T08:49:30.330174725Z 316 0 0 23293
2021-08-02T08:49:30.346282365Z 798 0 0 23187
2021-08-02T08:49:30.362351798Z 732 0 0 23187
2021-08-02T08:49:30.378310691Z 282 0 0 23187
2021-08-02T08:49:30.39422Z 549 0 0 23293
2021-08-02T08:49:30.410205143Z 615 0 0 23329
2021-08-02T08:49:30.42628595Z 149 0 0 23329
2021-08-02T08:49:30.442316883Z 282 0 0 23329
2021-08-02T08:49:30.45822561Z 582 0 0 23329
2021-08-02T08:49:30.474172836Z 133 0 0 23364
2021-08-02T08:49:30.490214269Z 233 0 0 23364
2021-08-02T08:49:30.506210203Z 549 0 0 23364
2021-08-02T08:49:30.522200303Z -399 0 0 23364
2021-08-02T08:49:30.538234736Z -366 0 0 23364
2021-08-02T08:49:30.554288127Z 0 23364
2021-08-02T08:49:30.570351727Z 0 23364
2021-08-02T08:49:30.586195413Z 0 23364
2021-08-02T08:49:30.602191055Z 0 23241
2021-08-02T08:49:30.618195155Z 0 23241
2021-08-02T08:49:30.634950578Z 0 23241
2021-08-02T08:49:30.650237772Z 0 23223
2021-08-02T08:49:30.666386828Z 0 23276
2021-08-02T08:49:30.682325013Z 0 23276
2021-08-02T08:49:30.698237823Z 0 23276
2021-08-02T08:49:30.714291797Z 0 23276
2021-08-02T08:49:30.730265564Z 0 23099
2021-08-02T08:49:30.746241957Z 0 23099
2021-08-02T08:49:30.762230307Z 0 23099
2021-08-02T08:49:30.778286615Z 0 23099
2021-08-02T08:49:30.794283132Z 0 22993
2021-08-02T08:49:30.819896051Z 0 23134
2021-08-02T08:49:30.826242917Z 0 23134
2021-08-02T08:49:30.84235989Z 0 23134
2021-08-02T08:49:30.86443611Z 0 23134
2021-08-02T08:49:30.874357007Z 0 23170
2021-08-02T08:49:30.890441315Z 0 23170
2021-08-02T08:49:30.906395249Z 0 23170
2021-08-02T08:49:30.922352392Z 0 23170
2021-08-02T08:49:30.942798927Z 0 23187
2021-08-02T08:49:30.954241427Z 0 23187
2021-08-02T08:49:30.970329818Z 0 23187
2021-08-02T08:49:30.986202379Z 0 23240
2021-08-02T08:49:31.002118397Z 0 23046
2021-08-02T08:49:31.018028873Z 0 23046
2021-08-02T08:49:31.034310053Z 0 23046
如您所见,有很多空值。
左列更有可能为空,最右列的字段键 voltage
永远不会有空值。
所以我猜想:同一行的filed value对应同一个时间戳,但不是同时写入数据库,可能有的写入了,有的没有写入。是吗?
有没有办法让同一个raw中的不同字段同时写入?所以我查询的时候同一行的每个字段都不为null。
或者怎么查询最近的所有字段都不为null的点?其实我想查询的是测量中的最后一个点:select * from "udp".."/controller/data" order by time desc limit 1
,但是它有时 returns 一些字段具有空值的点。
而且我发现 last()
对我的问题没有帮助。
因为如果我使用 SELECT last(*) FROM "udp".."/controller" WHERE time > now() - 1s
(我使用 WHERE
子句因为我认为它可以通过指定时间范围让它查询得更快),它只是合并 last(angular)
、[=25= 的结果], last(speed_right_rear)
, last(voltage)
成一分。但是字段值可能不对应相同的时间戳。
环境信息:
我运行所有这些程序都在类似于raspberryPi的嵌入设备nanopi上。
- 系统信息:Linux 4.4.179 aarch64
- InfluxDB 版本:1.8.7
配置: 我的 influx.conf
[[udp]]
enabled = true
batch-size = 50
batch-pending = 5
batch-timeout = "1s"
并且我尝试修改 UDP 批量大小以查看它是否有任何不同:
如果我在influxdb.conf
中修改batch-size为1[[udp]]
enabled = true
batch-size = 1
batch-pending = 5
batch-timeout = "1s"
会增加很多CPU负载,我只能获取时间>现在-22s
的点select * from "udp".."/controller/data" where time >= now() - 22s
它 returns 结果如下:
> SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 21s
name: /controller/data
time angular speed_left_rear speed_right_rear voltage
---- ------- --------------- ---------------- -------
1627894525069581596 599 0 0 23276
1627894525115397757 366 0 0 23116
1627894525147390263 782 0 0 23258
1627894525163375140 216 0 0 23258
1627894525179457142 449 0 0 23258
1627894525211368273 249 0 0 23382
1627894525227548857 532 0 0 23382
1627894525259374239 133 0 0 23382
1627894525275378367 249 0 0 23169
1627894525307387789 665 0 0 23169
1627894525323413499 499 0 0 23169
1627894525355366338 599 0 0 23311
1627894525371388841 382 0 0 23311
1627894525387508467 499 0 0 23311
1627894525403456887 1148 0 0 23223
1627894525420205921 549 0 0 23205
1627894525436119925 149 0 0 23205
1627894525452726045 366 0 0 23205
1627894525468630132 183 0 0 23223
1627894525484748008 -99 0 0 23223
1627894525500814260 249 0 0 23223
1627894525516629098 499 0 0 23223
1627894525533157344 848 0 0 23205
1627894525548644353 366 0 0 23205
1627894525564793437 16 0 0 23205
1627894525627496298 66 0 0 23347
1627894525675488264 83 0 0 23240
1627894525723471189 -33 0 0 23418
1627894525755489652 166 0 0 23418
1627894525772796929 332 0 0 23418
1627894525803355328 23152
有时它仍然是 returns 空值。 所以改batch size对这个问题不起作用,batch-size好像是属性一列,把一定量的列数据打包,然后写入数据库。
我不会使用 InfluxDB 处理最近 500 毫秒的数据。该软件不适用于此类解决方案。 InfluxDB 没有优先将所有值放在定义的时间。它不是实时系统。如果您需要类似的东西,我建议您使用实时 PLC 类型的设备。 但是......如果你想以这种方式使用它,我可以建议以下棘手的解决方案:
- 请求不更新的数据,例如 400ms:
SELECT last(*) FROM "udp".."/controller/data" WHERE time >= now() - 10s and time<=now()-400ms
假设在 400 毫秒后您在所有字段中都有值。 3)请求安全延迟的数据,例如500ms:
SELECT first(*) FROM "udp".."/controller/data" WHERE time >= now() - 500ms
上面的查询应该会在 500 毫秒后为您提供第一个值。假设需要不到 500 毫秒的时间来写入所有字段值。
- 使用 where 子句为所有值字段请求数据,如果那里只有数据,它将始终为真:
SELECT * FROM "udp".."/controller/data" WHERE time >= now() - 5s and "angular">-9999999 and "speed_left_rear">-9999999 and "speed_right_rear">-9999999"> and "voltage">-9999999 limit 1
以上所有假设您无法读取低于 -9999999 的值。 这样,您应该只收到所有值都已写入且不早于 5s 的系列。您将获得的值是与所有写入值具有相同时间戳的最新值。
和 2) 解决方案在某些条件下可能会工作或不工作,假设有延迟(这取决于系统工作负载等)。 3) 如果您需要所有具有相同时间戳的值,这可能是最佳解决方案。
另一种方法是进行 4 个独立查询,在其中查询最后一个值:
SELECT last(angular) FROM "udp".."/controller/data" SELECT last(speed_left_rear) FROM "udp".."/controller/data" SELECT last(speed_right_rear) FROM "udp".."/controller/data" SELECT last(voltage) FROM "udp".."/controller/data"
- 甚至在子查询中请求它:
Select * from (SELECT last(angular) as "angular" FROM "udp".."/controller/data"),(SELECT last(speed_left_rear) as "speed_left_rear" FROM "udp".."/controller/data"),(SELECT last(speed_right_rear) as "speed_right_rear" FROM "udp".."/controller/data"),(SELECT last(voltage) as "voltage" FROM "udp".."/controller/data")
它会给你最新的值,但它们可能没有相同的时间戳。