InfluxDB 架构设计和数据布局
此页面记录了早期版本的 InfluxDB OSS。InfluxDB OSS v2 是最新的稳定版本。请参阅 InfluxDB v2 文档。
每个 InfluxDB 用例都是独特的,您的 架构 反映了这种独特性。一般来说,为查询设计的架构会产生更简单、性能更高的查询。我们建议大多数用例遵循以下设计指南
数据存储位置(标签或字段)
您的查询应指导您将哪些数据存储在 标签 中,哪些数据存储在 字段 中
避免过多的序列
InfluxDB 索引以下数据元素以加速读取
标签值 已被索引,而 字段值 则未被索引。这意味着按标签查询比按字段查询性能更高。但是,当创建过多的索引时,写入和读取都可能开始减速。
每个唯一的索引数据元素集形成一个 序列键。标签 包含高度可变的信息,如唯一 ID、哈希和随机字符串,会导致大量的 序列,也称为高 序列基数。高序列基数是许多数据库工作负载中高内存使用率的主要驱动因素。因此,为了减少内存消耗,请考虑将高基数值存储在字段值中,而不是标签或字段键中。
如果对 InfluxDB 的读取和写入开始减速,您可能具有高序列基数(序列过多)。请参阅 如何查找和减少高序列基数。
使用推荐的命名约定
在命名标签和字段键时,请使用以下约定
避免在标签和字段键中使用保留关键字
不是必需的,但避免在标签和字段键中使用保留关键字可以简化编写查询,因为您不必将键用双引号括起来。请参阅 InfluxQL 和 Flux 关键字 以避免使用。
此外,如果标签或字段键包含 [A-z,_]
以外的字符,则必须在 InfluxQL 中用双引号括起来,或在 Flux 中使用 方括号表示法。
避免标签和字段使用相同的名称
避免对标签和字段键使用相同的名称。这通常会导致查询数据时出现意外行为。
如果您不小心为标签和字段添加了相同的名称,请参阅 常见问题,了解如何可预测地查询数据以及如何解决此问题。
避免在 measurements 和键中编码数据
将数据存储在 标签值 或 字段值 中,而不是 标签键、字段键 或 measurements 中。如果您将架构设计为将数据存储在标签和字段值中,您的查询将更易于编写且更有效率。
此外,您可以通过不将 measurements 和键创建为写入数据来保持低基数。要了解有关高序列基数对性能的影响的更多信息,请参阅 如何查找和减少高序列基数。
比较架构
比较以下以行协议表示的有效架构。
推荐:以下架构将元数据存储在单独的 crop
、plot
和 region
标签中。temp
字段包含可变的数值数据。
Good Measurements schema - Data encoded in tags (recommended)
-------------
weather_sensor,crop=blueberries,plot=1,region=north temp=50.1 1472515200000000000
weather_sensor,crop=blueberries,plot=2,region=midwest temp=49.8 1472515200000000000
不推荐:以下架构在 measurement 中连接存储多个属性(crop
、plot
和 region
)(blueberries.plot-1.north
),类似于 Graphite 指标。
Bad Measurements schema - Data encoded in the measurement (not recommended)
-------------
blueberries.plot-1.north temp=50.1 1472515200000000000
blueberries.plot-2.midwest temp=49.8 1472515200000000000
不推荐:以下架构在字段键中连接存储多个属性(crop
、plot
和 region
)(blueberries.plot-1.north
)。
Bad Keys schema - Data encoded in field keys (not recommended)
-------------
weather_sensor blueberries.plot-1.north.temp=50.1 1472515200000000000
weather_sensor blueberries.plot-2.midwest.temp=49.8 1472515200000000000
比较查询
比较 良好 Measurements 和 不良 Measurements 架构的以下查询。Flux 查询计算 north
区域中蓝莓的平均 temp
易于查询:良好 Measurements 数据很容易按 region
标签值过滤,如下例所示。
// Query *Good Measurements*, data stored in separate tag values (recommended)
from(bucket: "<database>/<retention_policy>")
|> range(start:2016-08-30T00:00:00Z)
|> filter(fn: (r) => r._measurement == "weather_sensor" and r.region == "north" and r._field == "temp")
|> mean()
难以查询:不良 Measurements 需要正则表达式从 measurement 中提取 plot
和 region
,如下例所示。
// Query *Bad Measurements*, data encoded in the measurement (not recommended)
from(bucket: "<database>/<retention_policy>")
|> range(start:2016-08-30T00:00:00Z)
|> filter(fn: (r) => r._measurement =~ /\.north$/ and r._field == "temp")
|> mean()
复杂的 measurements 使一些查询无法实现。例如,使用 不良 Measurements 架构不可能计算两个地块的平均温度。
InfluxQL 示例查询架构
# Query *Bad Measurements*, data encoded in the measurement (not recommended)
> SELECT mean("temp") FROM /\.north$/
# Query *Good Measurements*, data stored in separate tag values (recommended)
> SELECT mean("temp") FROM "weather_sensor" WHERE "region" = 'north'
避免在一个标签中放入多个信息
将包含多个部分的单个标签拆分为单独的标签可以简化您的查询并通过减少对正则表达式的需求来提高性能。
考虑以下以行协议表示的架构。
示例行协议架构
Schema 1 - Multiple data encoded in a single tag
-------------
weather_sensor,crop=blueberries,location=plot-1.north temp=50.1 1472515200000000000
weather_sensor,crop=blueberries,location=plot-2.midwest temp=49.8 1472515200000000000
架构 1 数据将多个单独的参数(plot
和 region
)编码到长标签值 (plot-1.north
) 中。将其与以下以行协议表示的架构进行比较。
Schema 2 - Data encoded in multiple tags
-------------
weather_sensor,crop=blueberries,plot=1,region=north temp=50.1 1472515200000000000
weather_sensor,crop=blueberries,plot=2,region=midwest temp=49.8 1472515200000000000
使用 Flux 或 InfluxQL 计算 north
区域中蓝莓的平均 temp
。架构 2 更可取,因为使用多个标签,您不需要正则表达式。
Flux 示例查询架构
// Schema 1 - Query for multiple data encoded in a single tag
from(bucket:"<database>/<retention_policy>")
|> range(start:2016-08-30T00:00:00Z)
|> filter(fn: (r) => r._measurement == "weather_sensor" and r.location =~ /\.north$/ and r._field == "temp")
|> mean()
// Schema 2 - Query for data encoded in multiple tags
from(bucket:"<database>/<retention_policy>")
|> range(start:2016-08-30T00:00:00Z)
|> filter(fn: (r) => r._measurement == "weather_sensor" and r.region == "north" and r._field == "temp")
|> mean()
InfluxQL 示例查询架构
# Schema 1 - Query for multiple data encoded in a single tag
> SELECT mean("temp") FROM "weather_sensor" WHERE location =~ /\.north$/
# Schema 2 - Query for data encoded in multiple tags
> SELECT mean("temp") FROM "weather_sensor" WHERE region = 'north'
分片组持续时间管理
分片组持续时间概述
InfluxDB 将数据存储在分片组中。分片组按 保留策略 (RP) 组织,并存储时间戳落在称为 分片持续时间 的特定时间间隔内的数据。
如果未提供分片组持续时间,则分片组持续时间由创建 RP 时的 RP 持续时间 确定。默认值为
RP 持续时间 | 分片组持续时间 |
---|---|
< 2 天 | 1 小时 |
>= 2 天且 <= 6 个月 | 1 天 |
> 6 个月 | 7 天 |
分片组持续时间也可以按 RP 配置。要配置分片组持续时间,请参阅 保留策略管理。
分片组持续时间权衡
确定最佳分片组持续时间需要在以下两者之间找到平衡
- 较长分片带来更好的整体性能
- 较短分片提供的灵活性
长分片组持续时间
较长的分片组持续时间允许 InfluxDB 在同一逻辑位置存储更多数据。这减少了数据重复,提高了压缩效率,并在某些情况下提高了查询速度。
短分片组持续时间
较短的分片组持续时间允许系统更有效地删除数据和记录增量备份。当 InfluxDB 执行 RP 时,它会删除整个分片组,而不是单个数据点,即使这些点比 RP 持续时间更旧。只有当分片组的持续时间结束时间早于 RP 持续时间时,才会删除分片组。
例如,如果您的 RP 持续时间为一天,则 InfluxDB 将每小时删除一小时的数据,并将始终有 25 个分片组。一天中每小时一个,以及一个部分过期的额外分片组,但在整个分片组早于 24 小时之前不会删除。
注意: 要考虑的特殊用例:按时间过滤架构数据(例如标签、序列、measurements)的查询。例如,如果您想在一个小时的时间间隔内过滤架构数据,则必须将分片组持续时间设置为 1 小时。有关更多信息,请参阅 按时间过滤架构数据。
分片组持续时间建议
默认分片组持续时间适用于大多数情况。但是,高吞吐量或长时间运行的实例将受益于使用更长的分片组持续时间。以下是一些更长分片组持续时间的建议
RP 持续时间 | 分片组持续时间 |
---|---|
<= 1 天 | 6 小时 |
> 1 天且 <= 7 天 | 1 天 |
> 7 天且 <= 3 个月 | 7 天 |
> 3 个月 | 30 天 |
无限 | 52 周或更长 |
注意: 请注意,
INF
(无限)不是 有效的分片组持续时间。在数据覆盖数十年且永远不会删除的极端情况下,像1040w
(20 年)这样的长分片组持续时间是完全有效的。
设置分片组持续时间之前要考虑的其他因素
回填的分片组持续时间
在过去的大时间范围内批量插入历史数据将立即触发创建大量分片。并发访问和写入数百或数千个分片的开销可能会迅速导致性能下降和内存耗尽。
在写入历史数据时,我们强烈建议临时设置更长的分片组持续时间,以便创建更少的分片。通常,52 周的分片组持续时间非常适合回填。
此页对您有帮助吗?
感谢您的反馈!
支持和反馈
感谢您成为我们社区的一份子!我们欢迎并鼓励您提供关于 InfluxDB 和本文档的反馈和错误报告。要获得支持,请使用以下资源
拥有年度合同或支持合同的客户 可以 联系 InfluxData 支持。