使用 InfluxDB 3 Last Value Cache 在 10 毫秒内查询最新值
作者:Scott Anderson / 开发者
2025 年 2 月 10 日
导航至
作为 InfluxDB 3 Core 和 InfluxDB 3 Enterprise 公共 Alpha 版本的一部分,Last Value Cache (LVC) 可供测试。 LVC 允许您缓存表中特定字段的最新值,从而提高查询性能,这些查询返回特定时间序列的字段的最新值或字段的最后 N 个值,这在许多监控工作负载中很常见。 使用 LVC,这些类型的查询在 10 毫秒内返回。
LVC 是一个内存缓存,用于存储表中时间序列的特定字段的最后 N 个值。 创建 LVC 时,您可以指定要缓存的字段、要包含在缓存中的标签(这决定了您存储最后值的唯一时间序列的数量)以及每个唯一标签集要缓存的值的数量。
例如,让我们使用具有以下架构的数据集(类似于家庭传感器示例数据集)
- home(表)
- 标签
- 房间
- 厨房
- 客厅
- 墙壁
- 北
- 东
- 南
- 房间
- 字段
- co(整数)
- temp(浮点数)
- hum(浮点数)
- 标签
如果要缓存每个房间和墙壁每个字段的最后一个值,LVC 将类似于这样
+-------------+-------+----+------+------+---------------------+
| room | wall | co | hum | temp | time |
+-------------+-------+----+------+------+---------------------+
| Kitchen | east | 26 | 36.5 | 22.7 | 2025-02-10T20:00:00 |
| Living Room | north | 17 | 36.4 | 22.2 | 2025-02-10T20:00:00 |
| Living Room | south | 16 | 36.3 | 22.1 | 2025-02-10T20:00:00 |
+-------------+-------+----+------+------+---------------------+
如果要缓存每个房间和墙壁每个字段的最后四个值,LVC 将类似于
+-------------+-------+----+------+------+---------------------+
| room | wall | co | hum | temp | time |
+-------------+-------+----+------+------+---------------------+
| Kitchen | east | 26 | 36.5 | 22.7 | 2025-02-10T20:00:00 |
| Kitchen | east | 9 | 36.0 | 22.7 | 2025-02-10T17:00:00 |
| Kitchen | east | 3 | 36.2 | 22.7 | 2025-02-10T15:00:00 |
| Kitchen | east | 0 | 36.1 | 22.7 | 2025-02-10T10:00:00 |
| Living Room | north | 17 | 36.4 | 22.2 | 2025-02-10T20:00:00 |
| Living Room | north | 5 | 35.9 | 22.6 | 2025-02-10T17:00:00 |
| Living Room | north | 1 | 36.1 | 22.3 | 2025-02-10T15:00:00 |
| Living Room | north | 0 | 36.0 | 21.8 | 2025-02-10T10:00:00 |
| Living Room | south | 16 | 36.3 | 22.1 | 2025-02-10T20:00:00 |
| Living Room | south | 4 | 35.8 | 22.5 | 2025-02-10T17:00:00 |
| Living Room | south | 0 | 36.0 | 22.3 | 2025-02-10T15:00:00 |
| Living Room | south | 0 | 35.9 | 21.8 | 2025-02-10T10:00:00 |
+-------------+-------+----+------+------+---------------------+
为什么要使用 Last Value Cache?
简而言之,LVC 在 10 毫秒内提供最后值的查询响应,从而简化了常见的查询类型。 假设您正在构建一个监控仪表板,并且只需要知道特定字段的最后报告值。 如果不使用 LVC,您必须运行类似于以下的查询
SELECT
room,
wall,
selector_last(co, time)['value'] as co,
selector_last(temp, time)['value'] as temp,
selector_last(hum, time)['value'] as hum,
selector_last(hum, time)['time'] AS time
FROM
home
GROUP BY
room,
wall
WHERE
time >= now() - INTERVAL '1 day'
AND time <= now()
虽然此查询将为您提供最后报告的值,但需要注意以下几点
- 每行中的时间值仅特定于
hum
字段。 如果字段值是独立报告的,且时间戳是零星的,则时间值对于其他字段可能不准确。 - 查询包括时间范围,这可以防止查询引擎必须读取表中的所有数据才能生成结果。 如果没有时间范围,此查询可能会非常“繁重”,具体取决于表中的数据量。 这也意味着,如果最后报告的值在查询的时间范围之外,则不会包含在结果中。
要从 LVC 查询相同的数据,查询将类似于
SELECT * FROM last_cache('home', 'homeSensorCache')
时间范围不是必需的。 所有返回的时间戳都特定于每个字段的最后报告值。 结果在 10 毫秒内返回,并且查询更简单。
LVC 还解锁了一些其他功能,但我们将在以后的文章中讨论。
设置 Last Value Cache
LVC 与表关联,表可以有多个 LVC。 您可以将 LVC 添加到现有表,但在此示例中,我们将创建一个新表来存储家庭传感器示例数据集。
- 使用
influxdb3 create table
命令创建一个新的home
表。 因为我们知道示例数据的架构,所以我们可以预先创建具有必要标签和字段列的表
influxdb3 create table \
--tags room \
--fields co:int64 temp:float64 hum:float64 \
--database example_db \
home
- 使用
influxdb3 create last_cache
命令创建一个与home
表关联的新 LVC。 您可以提供以下内容
- 表 (
--table
): (必需)要将 LVC 与之关联的表的名称。 - 缓存名称:缓存的唯一名称。 如果您未提供名称,InfluxDB 会自动为您生成缓存名称。
- 键列 (
--key-columns
): 指定要在缓存的主键中包含的列。 LVC 中的行由其时间戳和键列唯一标识,因此请包含标识每行所需的所有列。 这些通常是标签,但您可以使用以下类型的任何列- 字符串
- 整数
- 无符号整数
- 布尔值
- 值列 (
--value-columns
): 指定要缓存为值列的列。 这些通常是字段,但也可以是标签。 默认情况下,time
和指定为--key-columns
以外的列将缓存为值列。 - 计数 (
--count
): 每个唯一键列组合要缓存的值的数量。 默认计数为 1。
在此示例中,我们将创建一个名为 homeLastCache
的 LVC,该 LVC 与 home
表关联。 我们将使用 room
标签作为键列,所有字段作为值列,并且仅缓存每个房间每个字段的最新值
influxdb3 create last_cache \
--database example-db \
--table home \
--key-columns room \
homeLastCache
- 将数据写入与缓存关联的表。 对于此示例,写入家庭传感器示例数据(链接中提供了命令和数据,您可以调整数据的时间戳)。
注意:值在写入时缓存。 创建缓存后,它不会缓存先前写入的点,只会缓存新写入的点。
查询 Last Value Cache 中的数据
在 SQL SELECT
语句的 FROM
子句中使用 last_cache()
函数从 LVC 查询数据。 last_cache()
支持以下参数
- table_name:(必需)LVC 与之关联的表的名称,格式为字符串文字。
- cache_name:要从中查询的 LVC 的名称,格式为字符串文字(仅当表关联了多个 LVC 时才需要)。
last_cache(table_name, cache_name)
要查询 LVC 中写入的示例数据,请执行以下查询
SELECT * FROM last_cache('home', 'homeCache')
这只是一个简单的 SQL 查询,因此您可以包含其他 SQL 子句来修改查询结果。 例如,如果您只想获得厨房的最后温度值,可以使用以下查询
SELECT
room,
temp`
FROM
last_cache('home', 'homeCache')
WHERE
room = 'Kitchen'
注意:InfluxQL 不支持 last_cache()
函数,因此您只能使用 SQL 查询访问 LVC 中的数据。
关于 Last Value Cache 的须知
InfluxDB 3 Last Value Cache 是一个非常强大的工具,但在使用它时,有一些重要事项需要了解。 LVC 存储在内存中;缓存越大,维护它所需的内存就越多。 平衡 LVC 的大小与存储它们所需的内存量至关重要。 需要考虑的事项
高基数列
“基数”是指缓存数据中唯一键列组合的数量。 虽然 InfluxDB 3 存储引擎不受基数限制,但它确实会影响 LVC。 较高的基数会增加存储 LVC 的内存需求,并可能影响 LVC 查询性能。 我们建议以下内容
- 仅使用对您的查询工作负载重要的标签作为 LVC 中的键列。 不必要地缓存标签或字段作为键列会导致更高的基数,而没有任何好处。
- 避免在 LVC 中包含高基数列。
- 不要在 LVC 中包含多个高基数列
要大致了解 LVC 中键列的总基数,可以使用以下公式
num_uniq_col_val_N [× num_uniq_col_val_N …] = key_column_cardinality
值计数
通过增加 LVC 中要存储的值的数量,您将增加缓存中存储的行数以及存储它们所需的内存量。 对要存储的值的数量要谨慎。 此计数是每个唯一键列组合的计数。 如果您包含两个标签作为键列,一个具有三个唯一值,另一个具有 10 个唯一值,则您最多可以有 30 个唯一键列组合。 如果您想保留最后 10 个值,您可能会在缓存中拥有 300 多行。 实际上,这并不是一个巨大的缓存,但这说明了键列基数和您要缓存的值的数量如何使您的缓存大小呈指数级增长。
要了解缓存指定数量的值所需的行数,请使用以下公式
key_column_cardinality × count = number_of_rows
Last Value Cache 在服务器停止时会被刷新
由于 LVC 是内存缓存,因此每次服务器停止时都会刷新缓存。 服务器重启后,InfluxDB 仅在您写入数据时才将新值写入 LVC,因此可能有一段时间 LVC 中某些值不可用。
定义值列
创建 LVC 时,如果您包含 --value-columns
选项以指定要缓存为值列的字段,则将来添加的任何新字段都不会添加到缓存中。 但是,如果您省略 --value-columns
选项,则除指定为 --key-columns
的列之外的所有列都将缓存为值列,包括稍后添加的列。
分享您的反馈
InfluxDB 3 Last Value Cache 是一个强大的工具,可让您在需要返回最新报告值的查询中获得最佳性能。 它是您的时间序列工具箱中的另一个工具,可帮助确保您的工作负载尽可能高效。
试用 LVC,让我们知道您的想法! 查看我们的 Core 和 Enterprise 入门指南,并在 Discord 中的 #influxdb3_core 频道、Slack 中的 #influxdb3_core 频道或我们的社区网站上与我们的开发团队分享您的反馈。