InfluxDB 常见问题解答
此页面记录了早期版本的 InfluxDB OSS。InfluxDB OSS v2 是最新的稳定版本。请参阅 InfluxDB v2 文档。
此页面解决了常见的困惑来源以及 InfluxDB 相对于其他数据库系统表现出意外行为的地方。在适用的情况下,它链接到 GitHub 上的未解决问题。
管理
- 如何在密码中包含单引号?
- 如何识别我的 InfluxDB 版本?
- 在哪里可以找到 InfluxDB 日志?
- 分片组持续时间和保留策略之间的关系是什么?
- 为什么在我更改保留策略后数据没有被删除?
- 为什么 InfluxDB 无法解析配置文件中的微秒单位?
- InfluxDB 是否有文件系统大小限制?
命令行界面 (CLI)
- 如何使 InfluxDB 的 CLI 返回人类可读的时间戳?
- 非管理员用户如何在 InfluxDB CLI 中
USE
数据库? - 如何使用 InfluxDB CLI 写入非
DEFAULT
保留策略? - 如何取消长时间运行的查询?
数据类型
- 为什么我无法查询布尔字段值?
- InfluxDB 如何处理跨分片的字段类型差异?
- InfluxDB 可以存储的最小和最大整数是多少?
- InfluxDB 可以存储的最小和最大时间戳是多少?
- 如何判断字段中存储的数据类型?
- 我可以更改字段的数据类型吗?
InfluxQL 函数
查询数据
GROUP BY time()
查询返回的时间间隔由什么决定?- 为什么我的查询返回无数据或部分数据?
- 为什么我的
GROUP BY time()
查询不返回now()
之后发生的时间戳? - 我可以对时间戳执行数学运算吗?
- 我可以从返回的时间戳中识别写入精度吗?
- 在查询中,我应该何时使用单引号,何时使用双引号?
- 为什么在创建新的
DEFAULT
保留策略后我丢失了数据? - 为什么我的带有
WHERE OR
时间子句的查询返回空结果? - 为什么
fill(previous)
返回空结果? - 为什么我的
INTO
查询缺少数据? - 如何查询具有相同标签键和字段键的数据?
- 如何跨 measurement 查询数据?
- 时间戳的顺序重要吗?
- 如何
SELECT
具有无值的标签的数据?
序列和序列基数
写入数据
- 如何写入整数字段值?
- InfluxDB 如何处理重复点?
- InfluxDB API 需要什么换行符?
- 在向 InfluxDB 写入数据时,应避免哪些单词和字符?
- 在写入数据时,我应该何时使用单引号,何时使用双引号?
- 时间戳的精度重要吗?
- 对于写入稀疏的历史数据,配置建议和 schema 指南是什么?
如何在密码中包含单引号?
在创建密码和发送身份验证请求时,都使用反斜杠 (\
) 转义单引号。
如何识别我的 InfluxDB 版本?
有多种方法可以识别您正在使用的 InfluxDB 版本
在您的终端中运行 influxd version
$ influxd version
InfluxDB v1.12.0 (git: master b7bb7e8359642b6e071735b50ae41f5eb343fd42)
curl
/ping
端点
$ curl -i 'http://localhost:8086/ping'
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 1e08aeb6-fec0-11e6-8486-000000000000
X-Influxdb-Version: 1.12.0
Date: Wed, 01 Mar 2017 20:46:17 GMT
启动 InfluxDB 命令行界面
$ influx
Connected to http://localhost:8086version 1.12.0
InfluxDB shell version: 1.12.0
检查日志中的 HTTP 响应
$ journalctl -u influxdb.service
Mar 01 20:49:45 rk-api influxd[29560]: [httpd] 127.0.0.1 - - [01/Mar/2017:20:49:45 +0000] "POST /query?db=&epoch=ns&q=SHOW+DATABASES HTTP/1.1" 200 151 "-" "InfluxDBShell/1.12.0" 9a4371a1-fec0-11e6-84b6-000000000000 1709
在哪里可以找到 InfluxDB 日志?
在 System V 操作系统上,日志存储在 /var/log/influxdb/
下。
在 systemd 操作系统上,您可以使用 journalctl
访问日志。使用 journalctl -u influxdb
在日志中查看日志,或使用 journalctl -u influxdb > influxd.log
将日志打印到文本文件。使用 systemd,日志保留取决于您的系统的 journald 设置。
分片组持续时间和保留策略之间的关系是什么?
InfluxDB 将数据存储在分片组中。单个分片组覆盖特定的时间间隔;InfluxDB 通过查看相关保留策略 (RP) 的 DURATION
来确定该时间间隔。下表概述了 RP 的 DURATION
与分片组时间间隔之间的默认关系
RP 持续时间 | 分片组间隔 |
---|---|
< 2 天 | 1 小时 |
>= 2 天且 <= 6 个月 | 1 天 |
> 6 个月 | 7 天 |
用户还可以使用 CREATE RETENTION POLICY
和 ALTER RETENTION POLICY
语句配置分片组持续时间。使用 SHOW RETENTION POLICIES
语句检查您的保留策略的分片组持续时间。
为什么在我更改保留策略后数据没有被删除?
有几个因素可以解释为什么在保留策略 (RP) 更改后数据可能不会立即被删除。
第一个也是最可能的原因是,默认情况下,InfluxDB 每 30 分钟检查一次以强制执行 RP。您可能需要等待下一次 RP 检查,以便 InfluxDB 删除超出 RP 新 DURATION
设置的数据。30 分钟间隔是 可配置的。
其次,更改 RP 的 DURATION
和 SHARD DURATION
都可能导致意外的数据保留。InfluxDB 将数据存储在分片组中,这些分片组覆盖特定的 RP 和时间间隔。当 InfluxDB 强制执行 RP 时,它会删除整个分片组,而不是单个数据点。InfluxDB 无法分割分片组。
如果 RP 的新 DURATION
小于旧的 SHARD DURATION
,并且 InfluxDB 当前正在将数据写入旧的、较长的分片组之一,则系统被迫保留该分片组中的所有数据。即使该分片组中的某些数据超出了新的 DURATION
,也会发生这种情况。一旦该分片组的所有数据都超出新的 DURATION
,InfluxDB 将删除该分片组。然后,系统将开始将数据写入具有新的、较短的 SHARD DURATION
的分片组,从而防止任何进一步的意外数据保留。
为什么 InfluxDB 无法解析配置文件中的微秒单位?
对于 配置 设置、写入、查询以及在 InfluxDB 命令行界面 (CLI) 中设置精度,指定微秒持续时间单位的语法有所不同。下表显示了每个类别支持的语法
配置文件 | InfluxDB API 写入 | 所有查询 | CLI 精度命令 | |
---|---|---|---|---|
u | ❌ | 👍 | 👍 | 👍 |
us | 👍 | ❌ | ❌ | ❌ |
µ | ❌ | ❌ | 👍 | ❌ |
µs | 👍 | ❌ | ❌ | ❌ |
如果配置选项指定了 u
或 µ
语法,则 InfluxDB 无法启动并在日志中报告以下错误
run: parse config: time: unknown unit [µ|u] in duration [<integer>µ|<integer>u]
InfluxDB 是否有文件系统大小限制?
InfluxDB 在 Linux 和 Windows POSIX 的文件系统大小限制内工作。某些存储提供商和发行版具有大小限制;例如
- Amazon EBS 卷将大小限制为 ~16TB
- Linux ext3 文件系统将大小限制为 ~16TB
- Linux ext4 文件系统将大小限制为 ~1EB(文件大小限制为 ~16TB)
如果您预计每个卷/文件系统增长超过 16TB,我们建议您寻找支持您的存储要求的提供商和发行版。
如何使用 InfluxDB CLI 返回人类可读的时间戳?
当您首次连接到 CLI 时,请指定 rfc3339 精度
influx -precision rfc3339
或者,一旦您已连接到 CLI,就指定精度
$ influx
Connected to http://localhost:8086 version 0.xx.x
InfluxDB shell 0.xx.x
> precision rfc3339
>
查看 CLI/Shell 以获取更多有用的 CLI 选项。
非管理员用户如何在 InfluxDB CLI 中 USE
数据库?
在 v1.3 之前的版本中,即使 非管理员用户 对该数据库具有 READ
和/或 WRITE
权限,他们也无法在 CLI 中执行 USE <database_name>
查询。
从 1.3 版本开始,非管理员用户可以对他们具有 READ
和/或 WRITE
权限的数据库执行 USE <database_name>
查询。如果非管理员用户尝试 USE
他们没有 READ
和/或 WRITE
权限的数据库,系统将返回错误
ERR: Database <database_name> doesn't exist. Run SHOW DATABASES for a list of existing databases.
请注意,
SHOW DATABASES
查询 仅返回非管理员用户具有READ
和/或WRITE
权限的数据库。
如何使用 InfluxDB CLI 写入非 DEFAULT 保留策略?
使用语法 INSERT INTO [<database>.]<retention_policy> <line_protocol>
以使用 CLI 将数据写入非 DEFAULT
保留策略。(只有使用 CLI 才允许以这种方式指定数据库和保留策略。通过 HTTP 写入必须使用 db
和 rp
查询参数指定数据库,并可选择指定保留策略。)
例如
> INSERT INTO one_day mortality bool=true
Using retention policy one_day
> SELECT * FROM "mydb"."one_day"."mortality"
name: mortality
---------------
time bool
2016-09-13T22:29:43.229530864Z true
请注意,您将需要完全限定 measurement 才能查询非 DEFAULT
保留策略中的数据。使用以下语法完全限定 measurement
"<database>"."<retention_policy>"."<measurement>"
如何取消长时间运行的查询?
您可以使用 Ctrl+C
从 CLI 取消长时间运行的交互式查询。要停止在使用 SHOW QUERIES
命令时看到的其他长时间运行的查询,您可以使用 KILL QUERY
命令停止它。
为什么我无法查询布尔字段值?
可接受的布尔语法因数据写入和数据查询而异。
布尔语法 | 写入 | 查询 |
---|---|---|
t ,f | 👍 | ❌ |
T ,F | 👍 | ❌ |
true ,false | 👍 | 👍 |
True ,False | 👍 | 👍 |
TRUE ,FALSE | 👍 | 👍 |
例如,SELECT * FROM "hamlet" WHERE "bool"=True
返回所有 bool
设置为 TRUE
的点,但 SELECT * FROM "hamlet" WHERE "bool"=T
不返回任何内容。
InfluxDB 如何处理跨分片的字段类型差异?
字段值可以是浮点数、整数、字符串或布尔值。字段值类型在 分片 内不能不同,但它们可以跨分片 不同。
SELECT 语句
SELECT
语句 返回所有字段值,如果所有值都具有相同的类型。如果字段值类型跨分片不同,则 InfluxDB 首先执行任何适用的 转换 操作,然后返回类型在以下列表中首先出现的所有值:浮点数、整数、字符串、布尔值。
如果您的数据具有字段值类型差异,请使用语法 <field_key>::<type>
查询不同的数据类型。
示例
measurement just_my_type
具有一个名为 my_field
的字段。my_field
在四个不同的分片中具有四个字段值,并且每个值都具有不同的数据类型(浮点数、整数、字符串和布尔值)。
SELECT *
仅返回浮点数和整数字段值。请注意,InfluxDB 在响应中将整数值转换为浮点数。
SELECT * FROM just_my_type
name: just_my_type
------------------
time my_field
2016-06-03T15:45:00Z 9.87034
2016-06-03T16:45:00Z 7
SELECT <field_key>::<type> [...]
返回所有值类型。InfluxDB 在其自己的列中输出每种值类型,并带有递增的列名。在可能的情况下,InfluxDB 会将字段值转换为另一种类型;它将整数 7
转换为第一列中的浮点数,并将浮点数 9.879034
转换为第二列中的整数。InfluxDB 无法将浮点数或整数转换为字符串或布尔值。
SELECT "my_field"::float,"my_field"::integer,"my_field"::string,"my_field"::boolean FROM just_my_type
name: just_my_type
------------------
time my_field my_field_1 my_field_2 my_field_3
2016-06-03T15:45:00Z 9.87034 9
2016-06-03T16:45:00Z 7 7
2016-06-03T17:45:00Z a string
2016-06-03T18:45:00Z true
SHOW FIELD KEYS 查询
SHOW FIELD KEYS
返回与字段键关联的每个分片中的每种数据类型。
示例
measurement just_my_type
具有一个名为 my_field
的字段。my_field
在四个不同的分片中具有四个字段值,并且每个值都具有不同的数据类型(浮点数、整数、字符串和布尔值)。SHOW FIELD KEYS
返回所有四种数据类型
> SHOW FIELD KEYS
name: just_my_type
fieldKey fieldType
-------- ---------
my_field float
my_field string
my_field integer
my_field boolean
InfluxDB 可以存储的最小和最大整数是多少?
InfluxDB 将所有整数存储为有符号 int64 数据类型。int64 的最小和最大有效值分别为 -9223372036854775808
和 9223372036854775807
。有关更多信息,请参阅 Go builtins。
接近但仍在这些限制范围内的值可能会导致意外结果;某些函数和运算符在计算期间将 int64 数据类型转换为 float64,这可能会导致溢出问题。
InfluxDB 可以存储的最小和最大时间戳是多少?
最小时间戳为 -9223372036854775806
或 1677-09-21T00:12:43.145224194Z
。最大时间戳为 9223372036854775806
或 2262-04-11T23:47:16.854775806Z
。
超出该范围的时间戳会返回 解析错误。
如何判断字段中存储的数据类型?
SHOW FIELD KEYS
查询还会返回字段的类型。
示例
> SHOW FIELD KEYS FROM all_the_types
name: all_the_types
-------------------
fieldKey fieldType
blue string
green boolean
orange integer
yellow float
我可以更改字段的数据类型吗?
目前,InfluxDB 对更改字段的数据类型的支持非常有限。
<field_key>::<type>
语法支持将字段值从整数转换为浮点数,或从浮点数转换为整数。有关示例,请参阅 类型转换操作。无法将浮点数或整数转换为字符串或布尔值(反之亦然)。
我们在下面列出了更改字段数据类型的可能解决方法。请注意,这些解决方法不会更新已写入数据库的数据。
将数据写入不同的字段
最简单的解决方法是开始将新的数据类型写入同一 序列 中的不同字段。
处理分片系统
字段值类型在 分片 内不能不同,但它们可以跨分片不同。
希望更改字段数据类型的用户可以使用 SHOW SHARDS
查询来识别当前分片的 end_time
。如果点的时间戳发生在 end_time
之后,InfluxDB 将接受使用不同数据类型写入现有字段。
请注意,这不会更改先前分片上的字段数据类型。有关这如何影响您的查询,请参阅 InfluxDB 如何处理跨分片的字段类型差异。
如何在函数中执行数学运算?
目前,InfluxDB 不支持在函数中进行数学运算。我们建议使用 InfluxQL 的 子查询 作为解决方法。
示例
InfluxQL 不支持以下语法
SELECT MEAN("dogs" - "cats") from "pet_daycare"
相反,使用子查询来获得相同的结果
> SELECT MEAN("difference") FROM (SELECT "dogs" - "cat" AS "difference" FROM "pet_daycare")
有关更多信息,请参阅 数据探索 页面。
为什么我的查询返回 epoch 0 作为时间戳?
在 InfluxDB 中,epoch 0 (1970-01-01T00:00:00Z
) 通常用作空时间戳等效项。如果您请求一个没有时间戳返回的查询,例如具有无界时间范围的聚合函数,则 InfluxDB 返回 epoch 0 作为时间戳。
哪些 InfluxQL 函数支持嵌套?
以下 InfluxQL 函数支持嵌套
COUNT()
与DISTINCT()
CUMULATIVE_SUM()
DERIVATIVE()
DIFFERENCE()
ELAPSED()
MOVING_AVERAGE()
NON_NEGATIVE_DERIVATIVE()
HOLT_WINTERS()
和HOLT_WINTERS_WITH_FIT()
有关如何使用子查询代替嵌套函数的信息,请参阅 数据探索。
GROUP BY time()
查询返回的时间间隔由什么决定?
GROUP BY time()
查询返回的时间间隔符合 InfluxDB 数据库的预设时间桶或用户指定的 偏移间隔。
示例
预设时间桶
以下查询计算 sunflowers
在下午 6:15 到晚上 7:45 之间的平均值,并将这些平均值分组为一小时的间隔
SELECT mean("sunflowers")
FROM "flower_orders"
WHERE time >= '2016-08-29T18:15:00Z' AND time <= '2016-08-29T19:45:00Z' GROUP BY time(1h)
下面的结果显示了 InfluxDB 如何维护其预设时间桶。
在此示例中,下午 6 点的小时是一个预设桶,下午 7 点的小时是一个预设桶。下午 6 点时间桶的平均值不包括下午 6:15 之前的数据,因为 WHERE
时间子句,但包含在下午 6 点时间桶平均值中的任何数据都必须发生在下午 6 点的小时内。下午 7 点时间桶也是如此;包含在下午 7 点时间桶平均值中的任何数据都必须发生在下午 7 点的小时内。虚线显示了构成每个平均值的点。
请注意,虽然结果中的第一个时间戳是 2016-08-29T18:00:00Z
,但该桶中的查询结果不包括时间戳发生在 WHERE
时间子句开始之前(2016-08-29T18:15:00Z
)的数据。
原始数据:
结果
name: flower_orders name: flower_orders
————————— -------------------
time sunflowers time mean
2016-08-29T18:00:00Z 34 2016-08-29T18:00:00Z 22.332
|--| 2016-08-29T19:00:00Z 62.75
2016-08-29T18:15:00Z |28|
2016-08-29T18:30:00Z |19|
2016-08-29T18:45:00Z |20|
|--|
|--|
2016-08-29T19:00:00Z |56|
2016-08-29T19:15:00Z |76|
2016-08-29T19:30:00Z |29|
2016-08-29T19:45:00Z |90|
|--|
2016-08-29T20:00:00Z 70
偏移间隔
以下查询计算 sunflowers
在下午 6:15 到晚上 7:45 之间的平均值,并将这些平均值分组为一小时的间隔。它还将 InfluxDB 数据库的预设时间桶偏移 15
分钟。
SELECT mean("sunflowers")
FROM "flower_orders"
WHERE time >= '2016-08-29T18:15:00Z' AND time <= '2016-08-29T19:45:00Z' GROUP BY time(1h,15m)
---
|
offset interval
在此示例中,用户指定的 偏移间隔 将 InfluxDB 数据库的预设时间桶向前移动了 15
分钟。下午 6 点时间桶的平均值现在包括下午 6:15 到下午 7 点之间的数据,下午 7 点时间桶的平均值包括下午 7:15 到晚上 8 点之间的数据。虚线显示了构成每个平均值的点。
请注意,结果中的第一个时间戳是 2016-08-29T18:15:00Z
而不是 2016-08-29T18:00:00Z
。
原始数据:
结果
name: flower_orders name: flower_orders
————————— -------------------
time sunflowers time mean
2016-08-29T18:00:00Z 34 2016-08-29T18:15:00Z 30.75
|--| 2016-08-29T19:15:00Z 65
2016-08-29T18:15:00Z |28|
2016-08-29T18:30:00Z |19|
2016-08-29T18:45:00Z |20|
2016-08-29T19:00:00Z |56|
|--|
|--|
2016-08-29T19:15:00Z |76|
2016-08-29T19:30:00Z |29|
2016-08-29T19:45:00Z |90|
2016-08-29T20:00:00Z |70|
|--|
为什么我的查询返回无数据或部分数据?
您的查询返回无数据或部分数据的最常见原因
- 查询错误的保留策略(未返回数据)
- SELECT 子句中没有字段键(未返回数据)
- SELECT 查询包含
GROUP BY time()
(返回now()
之前的部分数据) - 标签键和字段键具有相同的名称
查询错误的保留策略
InfluxDB 自动查询数据库的默认 保留策略 (RP) 中的数据。如果您的数据存储在另一个 RP 中,您必须在查询中指定 RP 才能获得结果。
SELECT 子句中没有字段键
查询的 SELECT
子句中至少需要一个 字段键。如果 SELECT
子句仅包含 标签键,则查询返回空响应。有关更多信息,请参阅 数据探索。
SELECT 查询包含 GROUP BY time()
如果您的 SELECT
查询包含 GROUP BY time()
子句,则仅返回 1677-09-21 00:12:43.145224194
和 now()
之间的数据点。因此,如果您的任何数据点发生在 now()
之后,请在您的时间间隔中指定 替代上限。
(默认情况下,大多数 SELECT
查询 查询时间戳介于 1677-09-21 00:12:43.145224194
和 2262-04-11T23:47:16.854775806Z
UTC 之间的数据。)
标签键和字段键具有相同的名称
避免对标签键和字段键使用相同的名称。如果您不小心为标签键和字段键添加了相同的名称,然后一起查询这两个键,则查询结果会显示第二个查询的键(标签或字段)附加了 _1
(在 Chronograf 中也可见为列标题)。要查询附加了 _1
的标签或字段键,您必须删除附加的 _1
并包含语法 ::tag
或 ::field
。
示例
写入以下点以创建具有相同名称
leaves
的字段和标签键# create the `leaves` tag key INSERT grape,leaves=species leaves=6 #create the `leaves` field key INSERT grape leaves=5
如果您查看这两个键,您会注意到这两个键都不包含
_1
# show the `leaves` tag key SHOW TAG KEYS name: grape tagKey ------ leaves # create the `leaves` field key SHOW FIELD KEYS name: grape fieldKey fieldType ------ --------- leaves float
如果您查询
grape
measurement,您会看到leaves
标签键已附加_1
# query the `grape` measurement SELECT * FROM <database_name>.<retention_policy>."grape" name: grape time leaves leaves_1 ---- -------- ---------- 1574128162128468000 6.00 species 1574128238044155000 5.00
要查询重复的键名,您必须删除
_1
并包含键之后的::tag
或::field
# query duplicate keys using the correct syntax SELECT "leaves"::tag, "leaves"::field FROM <database_name>.<retention_policy>."grape" name: grape time leaves leaves_1 ---- -------- ---------- 1574128162128468000 species 6.00 1574128238044155000 5.00
因此,引用
leaves_1
的查询不会返回值。
警告: 如果您不小心添加了重复的键名,请按照以下步骤 删除重复的键。由于内存要求,如果您有大量数据,我们建议您按指定的时间间隔(例如,日期范围)对数据进行分块(在选择数据时),以适应分配的内存。
删除重复的键
使用以下查询删除重复的键。
/* select each field key to keep in the original measurement and send to a temporary measurement; then, group by the tag keys to keep (leave out the duplicate key) */ SELECT "field_key","field_key2","field_key3" INTO <temporary_measurement> FROM <original_measurement> WHERE <date range> GROUP BY "tag_key","tag_key2","tag_key3" /* verify the field keys and tags keys were successfully moved to the temporary measurement */ SELECT * FROM "temporary_measurement" /* drop original measurement (with the duplicate key) */ DROP MEASUREMENT "original_measurement" /* move data from temporary measurement back to original measurement you just dropped */ SELECT * INTO "original_measurement" FROM "temporary_measurement" GROUP BY * /* verify the field keys and tags keys were successfully moved back to the original measurement */ SELECT * FROM "original_measurement" /* drop temporary measurement */ DROP MEASUREMENT "temporary_measurement"
为什么我的 GROUP BY time() 查询不返回 now() 之后发生的时间戳?
大多数 SELECT
语句的默认时间范围介于 1677-09-21 00:12:43.145224194
和 2262-04-11T23:47:16.854775806Z
UTC 之间。对于带有 GROUP BY time()
子句 的 SELECT
语句,默认时间范围介于 1677-09-21 00:12:43.145224194
UTC 和 now()
之间。
要查询时间戳发生在 now()
之后的数据,带有 GROUP BY time()
子句的 SELECT
语句必须在 WHERE
子句 中提供替代上限。
在以下示例中,第一个查询涵盖时间戳介于 2015-09-18T21:30:00Z
和 now()
之间的数据。第二个查询涵盖时间戳介于 2015-09-18T21:30:00Z
和 now()
起 180 周之间的数据。
> SELECT MEAN("boards") FROM "hillvalley" WHERE time >= '2015-09-18T21:30:00Z' GROUP BY time(12m) fill(none)
> SELECT MEAN("boards") FROM "hillvalley" WHERE time >= '2015-09-18T21:30:00Z' AND time <= now() + 180w GROUP BY time(12m) fill(none)
请注意,WHERE
子句必须提供替代上限才能覆盖默认的 now()
上限。以下查询仅将下限重置为 now()
,以便查询的时间范围介于 now()
和 now()
之间
> SELECT MEAN("boards") FROM "hillvalley" WHERE time >= now() GROUP BY time(12m) fill(none)
>
有关查询中时间语法的更多信息,请参阅 数据探索。
我可以对时间戳执行数学运算吗?
目前,无法在 InfluxDB 中对时间戳值执行数学运算符。大多数时间计算必须由接收查询结果的客户端执行。
对时间戳值使用 InfluxQL 函数的支持有限。函数 ELAPSED() 返回单个字段中后续时间戳之间的差值。
我可以从返回的时间戳中识别写入精度吗?
InfluxDB 将所有时间戳存储为纳秒值,无论提供的写入精度如何。重要的是要注意,当返回查询结果时,数据库会静默地从时间戳中删除尾随零,这会掩盖初始写入精度。
在下面的示例中,标签 precision_supplied
和 timestamp_supplied
显示了用户在写入时提供的时间精度和时间戳。由于 InfluxDB 会静默地删除返回时间戳中的尾随零,因此在返回的时间戳中无法识别写入精度。
name: trails
-------------
time value precision_supplied timestamp_supplied
1970-01-01T01:00:00Z 3 n 3600000000000
1970-01-01T01:00:00Z 5 h 1
1970-01-01T02:00:00Z 4 n 7200000000000
1970-01-01T02:00:00Z 6 h 2
在查询中,我应该何时使用单引号,何时使用双引号?
单引号字符串值(例如,标签值),但不要单引号标识符(数据库名称、保留策略名称、用户名、measurement 名称、标签键和字段键)。
如果标识符以数字开头、包含 [A-z,0-9,_]
以外的字符,或者如果是 InfluxQL 关键字,则使用双引号引用标识符。如果标识符不属于这些类别之一,则不需要双引号,但我们建议无论如何都使用双引号引用它们。
示例
是:SELECT bikes_available FROM bikes WHERE station_id='9'
是:SELECT "bikes_available" FROM "bikes" WHERE "station_id"='9'
是:SELECT MIN("avgrq-sz") AS "min_avgrq-sz" FROM telegraf
是:SELECT * from "cr@zy" where "p^e"='2'
否:SELECT 'bikes_available' FROM 'bikes' WHERE 'station_id'="9"
否:SELECT * from cr@zy where p^e='2'
单引号日期时间字符串。如果您双引号日期时间字符串,InfluxDB 会返回错误 (ERR: invalid operation: time and *influxql.VarRef are not compatible
)。
示例
是:SELECT "water_level" FROM "h2o_feet" WHERE time > '2015-08-18T23:00:01.232000000Z' AND time < '2015-09-19'
否:SELECT "water_level" FROM "h2o_feet" WHERE time > "2015-08-18T23:00:01.232000000Z" AND time < "2015-09-19"
有关查询中时间语法的更多信息,请参阅 数据探索。
为什么在创建新的 DEFAULT 保留策略后我丢失了数据?
当您在数据库上创建新的 DEFAULT
保留策略 (RP) 时,写入旧 DEFAULT
RP 的数据仍保留在旧 RP 中。不指定 RP 的查询会自动查询新的 DEFAULT
RP,因此旧数据可能看起来丢失了。要查询旧数据,您必须在查询中完全限定相关数据。
示例
measurement fleeting
中的所有数据都属于名为 one_hour
的 DEFAULT
RP(保留策略)
> SELECT count(flounders) FROM fleeting
name: fleeting
--------------
time count
1970-01-01T00:00:00Z 8
我们 创建 一个新的 DEFAULT
RP (two_hour
) 并执行相同的查询
> SELECT count(flounders) FROM fleeting
>
要查询旧数据,我们必须通过完全限定 fleeting
来指定旧的 DEFAULT
RP
> SELECT count(flounders) FROM fish.one_hour.fleeting
name: fleeting
--------------
time count
1970-01-01T00:00:00Z 8
为什么我的带有 WHERE OR
时间子句的查询返回空结果?
目前,InfluxDB 不支持在 WHERE
子句中使用 OR
来指定多个时间范围。如果查询的 WHERE
子句将 OR
与时间间隔一起使用,InfluxDB 将返回空响应。
示例
> SELECT * FROM "absolutismus" WHERE time = '2016-07-31T20:07:00Z' OR time = '2016-07-31T23:07:17Z'
>
为什么 fill(previous)
返回空结果?
如果前一个值在查询的时间范围之外,则 fill(previous)
不会填充时间桶的结果。
在以下示例中,InfluxDB 不会使用 2016-07-12T16:50:00Z
-2016-07-12T16:50:10Z
时间桶的结果填充 2016-07-12T16:50:20Z
-2016-07-12T16:50:30Z
时间桶,因为查询的时间范围不包括较早的时间桶。
原始数据
> SELECT * FROM "cupcakes"
name: cupcakes
--------------
time chocolate
2016-07-12T16:50:00Z 3
2016-07-12T16:50:10Z 2
2016-07-12T16:50:40Z 12
2016-07-12T16:50:50Z 11
GROUP BY time()
查询
> SELECT max("chocolate") FROM "cupcakes" WHERE time >= '2016-07-12T16:50:20Z' AND time <= '2016-07-12T16:51:10Z' GROUP BY time(20s) fill(previous)
name: cupcakes
--------------
time max
2016-07-12T16:50:20Z
2016-07-12T16:50:40Z 12
2016-07-12T16:51:00Z 12
虽然这是 fill(previous)
的预期行为,但 GitHub 上的一个 开放功能请求 建议即使前一个值在查询的时间范围之外,fill(previous)
也应填充结果。
为什么我的 INTO 查询缺少数据?
默认情况下,INTO
查询会将初始数据中的任何标签转换为新写入数据中的字段。这可能会导致 InfluxDB 覆盖先前由标签区分的 数据点。在所有 INTO
查询中包含 GROUP BY *
以保留新写入数据中的标签。
请注意,此行为不适用于使用 TOP()
或 BOTTOM()
函数的查询。有关更多信息,请参阅 TOP()
和 BOTTOM()
文档。
示例
初始数据
french_bulldogs
measurement 包含 color
标签和 name
字段。
> SELECT * FROM "french_bulldogs"
name: french_bulldogs
---------------------
time color name
2016-05-25T00:05:00Z peach nugget
2016-05-25T00:05:00Z grey rumple
2016-05-25T00:10:00Z black prince
不带 GROUP BY *
的 INTO
查询
不带 GROUP BY *
子句的 INTO
查询将 color
标签转换为新写入数据中的字段。在初始数据中,nugget
数据点和 rumple
数据点仅通过 color
标签区分。一旦 color
成为字段,InfluxDB 就会认为 nugget
数据点和 rumple
数据点是重复的数据点,并且它会用 rumple
数据点覆盖 nugget
数据点。
> SELECT * INTO "all_dogs" FROM "french_bulldogs"
name: result
------------
time written
1970-01-01T00:00:00Z 3
> SELECT * FROM "all_dogs"
name: all_dogs
--------------
time color name
2016-05-25T00:05:00Z grey rumple <---- no more nugget 🐶
2016-05-25T00:10:00Z black prince
带 GROUP BY *
的 INTO
查询
带有 GROUP BY *
子句的 INTO
查询将 color
保留为新写入数据中的标签。在这种情况下,nugget
数据点和 rumple
数据点仍然是唯一的数据点,并且 InfluxDB 不会覆盖任何数据。
> SELECT "name" INTO "all_dogs" FROM "french_bulldogs" GROUP BY *
name: result
------------
time written
1970-01-01T00:00:00Z 3
> SELECT * FROM "all_dogs"
name: all_dogs
--------------
time color name
2016-05-25T00:05:00Z peach nugget
2016-05-25T00:05:00Z grey rumple
2016-05-25T00:10:00Z black prince
如何查询具有相同标签键和字段键的数据?
使用 ::
语法来指定键是字段键还是标签键。
示例
示例数据
> INSERT candied,almonds=true almonds=50,half_almonds=51 1465317610000000000
> INSERT candied,almonds=true almonds=55,half_almonds=56 1465317620000000000
> SELECT * FROM "candied"
name: candied
-------------
time almonds almonds_1 half_almonds
2016-06-07T16:40:10Z 50 true 51
2016-06-07T16:40:20Z 55 true 56
指定键是字段
> SELECT * FROM "candied" WHERE "almonds"::field > 51
name: candied
-------------
time almonds almonds_1 half_almonds
2016-06-07T16:40:20Z 55 true 56
指定键是标签
> SELECT * FROM "candied" WHERE "almonds"::tag='true'
name: candied
-------------
time almonds almonds_1 half_almonds
2016-06-07T16:40:10Z 50 true 51
2016-06-07T16:40:20Z 55 true 56
如何跨 measurement 查询数据?
目前,没有办法执行跨 measurement 的数学运算或分组。所有数据必须在单个 measurement 下才能一起查询。InfluxDB 不是关系数据库,跨 measurement 映射数据目前不是推荐的 schema(模式)。有关在 InfluxDB 中实现 JOIN 的讨论,请参阅 GitHub Issue #3552。
时间戳的顺序重要吗?
否。我们的测试表明,InfluxDB 完成以下查询所需的时间只有微不足道的差异
SELECT ... FROM ... WHERE time > 'timestamp1' AND time < 'timestamp2'
SELECT ... FROM ... WHERE time < 'timestamp2' AND time > 'timestamp1'
如何使用没有值的标签 SELECT 数据?
使用 ''
指定一个空的标签值。例如
> SELECT * FROM "vases" WHERE priceless=''
name: vases
-----------
time origin priceless
2016-07-20T18:42:00Z 8
为什么序列基数很重要?
InfluxDB 维护系统中每个 series(序列)的内存索引。随着唯一序列数量的增长,RAM 使用量也会增加。高 series cardinality(序列基数)可能导致操作系统使用内存不足 (OOM) 异常终止 InfluxDB 进程。请参阅 SHOW CARDINALITY 以了解有关序列基数的 InfluxSQL 命令。
如何从索引中删除序列?
要降低序列基数,必须从索引中删除序列。DROP DATABASE
、DROP MEASUREMENT
和 DROP SERIES
都将从索引中删除序列并降低总体序列基数。
注意:
DROP
命令通常是 CPU 密集型的,因为它们经常触发 TSM 压缩。以高频率发出DROP
查询可能会显着影响写入和其他查询吞吐量。
如何写入整数字段值?
写入整数时,在字段值的末尾添加一个尾随 i
。如果您不提供 i
,InfluxDB 会将字段值视为浮点数。
写入整数:value=100i
写入浮点数:value=100
InfluxDB 如何处理重复点?
一个数据点由 measurement 名称、tag set(标签集)和时间戳唯一标识。如果您提交一个与现有数据点具有相同 measurement、标签集和时间戳的新数据点,则字段集将成为旧字段集和新字段集的并集,其中任何冲突都归于新字段集。这是预期的行为。
例如
旧数据点:cpu_load,hostname=server02,az=us_west val_1=24.5,val_2=7 1234567890000000
新数据点:cpu_load,hostname=server02,az=us_west val_1=5.24 1234567890000000
提交新数据点后,InfluxDB 会用新字段值覆盖 val_1
,并保持字段 val_2
不变
> SELECT * FROM "cpu_load" WHERE time = 1234567890000000
name: cpu_load
--------------
time az hostname val_1 val_2
1970-01-15T06:56:07.89Z us_west server02 5.24 7
要存储两个数据点
引入一个任意的新标签以强制唯一性。
旧数据点:
cpu_load,hostname=server02,az=us_west,uniq=1 val_1=24.5,val_2=7 1234567890000000
新数据点:
cpu_load,hostname=server02,az=us_west,uniq=2 val_1=5.24 1234567890000000
将新数据点写入 InfluxDB 后
> SELECT * FROM "cpu_load" WHERE time = 1234567890000000 name: cpu_load -------------- time az hostname uniq val_1 val_2 1970-01-15T06:56:07.89Z us_west server02 1 24.5 7 1970-01-15T06:56:07.89Z us_west server02 2 5.24
将时间戳增加一纳秒。
旧数据点:
cpu_load,hostname=server02,az=us_west val_1=24.5,val_2=7 1234567890000000
新数据点:
cpu_load,hostname=server02,az=us_west val_1=5.24 1234567890000001
将新数据点写入 InfluxDB 后
> SELECT * FROM "cpu_load" WHERE time >= 1234567890000000 and time <= 1234567890000001 name: cpu_load -------------- time az hostname val_1 val_2 1970-01-15T06:56:07.89Z us_west server02 24.5 7 1970-01-15T06:56:07.890000001Z us_west server02 5.24
InfluxDB API 需要什么换行符?
InfluxDB 行协议依赖于换行符 (\n
,即 ASCII 0x0A
) 来指示行的结尾和新行的开始。使用 \n
以外的换行符的文件或数据将导致以下错误:bad timestamp
,unable to parse
。
请注意,Windows 使用回车符和换行符 (\r\n
) 作为换行符。
在向 InfluxDB 写入数据时,应避免哪些单词和字符?
InfluxQL 关键字
如果您使用 InfluxQL 关键字 作为标识符,您需要在每个查询中用双引号引起来。这可能会导致 非直观的错误。标识符是连续查询名称、数据库名称、字段键、measurement 名称、保留策略名称、订阅名称、标签键和用户名。
time
关键字 time
是一种特殊情况。time
可以是 continuous query(连续查询)名称、数据库名称、measurement(measurement)名称、retention policy(保留策略)名称、subscription(订阅)名称和 user(用户)名。在这些情况下,time
在查询中不需要双引号。time
不能是 field key(字段键)或 tag key(标签键);InfluxDB 拒绝将 time
作为字段键或标签键的写入,并返回错误。
示例
将 time
写入为 measurement 并查询它
> INSERT time value=1
> SELECT * FROM time
name: time
time value
---- -----
2017-02-07T18:28:27.349785384Z 1
time
是 InfluxDB 中有效的 measurement 名称。
将 time
写入为字段键并尝试查询它
> INSERT mymeas time=1
ERR: {"error":"partial write: invalid field name: input field \"time\" on measurement \"mymeas\" is invalid dropped=1"}
time
不是 InfluxDB 中有效的字段键。系统不会写入数据点并返回 400
。
将 time
写入为标签键并尝试查询它
> INSERT mymeas,time=1 value=1
ERR: {"error":"partial write: invalid tag key: input tag \"time\" on measurement \"mymeas\" is invalid dropped=1"}
time
不是 InfluxDB 中有效的标签键。系统不会写入数据点并返回 400
。
字符
为了保持正则表达式和引用简单,请避免在标识符中使用以下字符
\
反斜杠 ^
抑扬符 $
美元符号 '
单引号 "
双引号 =
等号 ,
逗号
在写入数据时,我应该何时使用单引号,何时使用双引号?
通过行协议写入数据时,避免使用单引号和双引号引用标识符;请参阅下面的示例,了解如何使用引号写入标识符会使查询复杂化。标识符是数据库名称、保留策略名称、用户名、measurement 名称、标签键和字段键。
使用双引号 measurement 写入:
INSERT "bikes" bikes_available=3
适用查询:SELECT * FROM "\"bikes\""
使用单引号 measurement 写入:
INSERT 'bikes' bikes_available=3
适用查询:SELECT * FROM "\'bikes\'"
使用未加引号的 measurement 写入:
INSERT bikes bikes_available=3
适用查询:SELECT * FROM "bikes"
用双引号引用作为字符串的字段值。
写入:
INSERT bikes happiness="level 2"
适用查询:SELECT * FROM "bikes" WHERE "happiness"='level 2'
特殊字符应使用反斜杠转义,而不是放在引号中。
写入:
INSERT wacky va\"ue=4
适用查询:SELECT "va\"ue" FROM "wacky"
有关更多信息,请参阅 行协议。
时间戳的精度重要吗?
是的。为了最大限度地提高性能,在将数据写入 InfluxDB 时,请使用尽可能粗略的时间戳精度。
在以下两个示例中,第一个请求使用纳秒的默认精度,而第二个示例将精度设置为秒
curl -i -XPOST "http://localhost:8086/write?db=weather" --data-binary 'temperature,location=1 value=90 1472666050000000000'
curl -i -XPOST "http://localhost:8086/write?db=weather&precision=s" --data-binary 'temperature,location=1 value=90 1472666050'
权衡是,具有重复时间戳的相同数据点(随着精度变粗,这种情况更有可能发生)可能会覆盖其他数据点。
对于写入稀疏的历史数据,配置建议和 schema 指南是什么?
对于想要将稀疏的历史数据写入 InfluxDB 的用户,InfluxData 建议
首先,延长您的 retention policy(保留策略)的 shard group(分片组)持续时间,以涵盖数年。默认分片组持续时间为一周,如果您的数据涵盖数百年 - 嗯,那将有很多分片!拥有极高数量的分片对于 InfluxDB 来说效率低下。使用 ALTER RETENTION POLICY
查询 增加数据保留策略的分片组持续时间。
其次,暂时降低 cache-snapshot-write-cold-duration
配置设置。如果您要写入大量历史数据,默认设置 (10m
) 可能会导致系统为每个分片将所有数据保存在缓存中。在您写入历史数据时,暂时将 cache-snapshot-write-cold-duration
设置降低到 10s
会使该过程更有效率。
此页是否对您有帮助?
感谢您的反馈!
支持和反馈
感谢您成为我们社区的一份子!我们欢迎并鼓励您提供有关 InfluxDB 和本文档的反馈和错误报告。要获得支持,请使用以下资源
拥有年度合同或支持合同的客户 可以 联系 InfluxData 支持。