InfluxDB Enterprise 常见问题解答
本页面解决了常见的混淆源和 InfluxDB 相对于其他数据库系统表现出意外行为的地方。 适用时,它链接到 GitHub 上的突出问题。
管理
- 我如何在密码中包含单引号?
- 我怎么可以识别我使用的InfluxDB版本?
- 我在哪里可以找到InfluxDB日志?
- 分片组持续时间与保留策略之间有什么关系?
- 为什么在我更改保留策略后数据没有被删除?
- 为什么 InfluxDB 无法解析配置文件中的微秒单位?
- InfluxDB是否有文件系统大小限制?
命令行接口 (CLI)
- 如何使InfluxDB的CLI返回可读的人类时间戳?
- 非管理员用户如何在 InfluxDB CLI 中
USE一个数据库? - 如何使用InfluxDB命令行工具写入非
DEFAULT保留策略? - 我如何取消一个长时间运行的查询?
数据类型
- 为什么我无法查询布尔字段值?
- InfluxDB 如何处理分片之间的字段类型差异?
- InfluxDB可以存储的最小和最大整数是多少?
- InfluxDB 能存储的最小和最大时间戳是什么?
- 我如何知道一个字段中存储的数据类型?
- 我可以更改字段的数据类型吗?
InfluxQL 函数
查询数据
- 是什么决定了
GROUP BY time()查询返回的时间间隔? - 为什么我的查询返回没有数据或部分数据?
- 为什么我的
GROUP BY time()查询不返回在now()之后发生的时间戳? - 我可以对时间戳进行数学运算吗?
- 我可以根据返回的时间戳识别写入精度吗?
- 在查询中我应该什么时候使用单引号,什么时候使用双引号?
- 为什么在创建新的
DEFAULT保留策略后会丢失数据? - 为什么我的查询带有
WHERE OR时间条件会返回空结果? - 为什么
fill(previous)返回空结果? - 为什么我的
INTO查询缺少数据? - 我如何查询具有相同标签键和字段键的数据?
- 我如何跨测量查询数据?
- 时间戳的顺序重要吗?
- 我如何使用
SELECT选择没有值的标签的数据?
系列和系列基数
写入数据
- 我该如何编写整数字段值?
- InfluxDB如何处理重复点?
- InfluxDB API 要求使用什么换行符?
- 在写入数据到InfluxDB时,我应该避免使用哪些词汇和字符?
- 在写数据时,何时应该使用单引号,何时应该使用双引号?
- 时间戳的精度重要吗?
- 编写稀疏历史数据的配置建议和架构指南是什么?
日志错误
- 在哪里可以找到InfluxDB Enterprise日志?
- 为什么我在我的元节点日志中看到
503 Service Unavailable错误? - 为什么在我的一些数据节点日志中看到
409错误? - 为什么在我的数据节点日志中看到
hinted handoff queue not empty错误? - 为什么我在数据节点日志中看到
error writing count stats ...: partial write错误? - 为什么我在数据节点日志中看到
queue is full错误? - 我为什么在尝试使用
influxd-ctl join添加元节点时看到unable to determine if "hostname" is a meta node? - 为什么当我的系统有空闲内存时,InfluxDB 报告内存不足 (OOM) 异常?
如何在密码中包含单引号?
在创建密码和发送身份验证请求时,用反斜杠 (\) 转义单引号。
如何识别我的InfluxDB版本?
有多种方法可以识别您正在使用的InfluxDB版本:
在您的终端中运行 influxd version:
$ influxd version
InfluxDB v1.11.8 (git: master b7bb7e8359642b6e071735b50ae41f5eb343fd42)
调用 /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.11.8
Date: Wed, 01 Mar 2017 20:46:17 GMT
启动 InfluxDB 命令行界面:
$ influx
Connected to http://localhost:8086 version 1.11.8
InfluxDB shell version: 1.11.8
检查您日志中的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.11.8" 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 | ❌ | 👍 | 👍 | 👍 |
| 美国 | 👍 | ❌ | ❌ | ❌ |
| µ | ❌ | ❌ | 👍 | ❌ |
| 微秒 | 👍 | ❌ | ❌ | ❌ |
如果配置选项指定了 u 或 µ 语法,InfluxDB 将无法启动,并在日志中报告以下错误:
run: parse config: time: unknown unit [µ|u] in duration [<integer>µ|<integer>u]
InfluxDB是否有文件系统大小限制?
InfluxDB 在 Linux 和 Windows POSIX 的文件系统大小限制内工作。一些存储提供商和发行版有大小限制;例如:
- 亚马逊EBS卷的大小限制为约16TB
- Linux ext3文件系统限制大小 ~16TB
- Linux ext4 文件系统的大小限制为约 1EB(文件大小限制约为 16TB)
如果您预期每个卷/文件系统的增长超过16TB,我们建议您找到一个支持您存储需求的服务提供商和分发。
我如何使用InfluxDB命令行接口返回可读的时间戳?
当您第一次连接到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写入非默认的保留策略?
使用语法 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
请注意,您需要完全限定测量才能查询非DEFAULT保留策略中的数据。 使用以下语法完全限定测量:
"<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 语句 将返回所有字段值。 如果字段值类型在分片之间不同,InfluxDB 首先执行任何适用的 cast 操作,然后返回以下列表中首次出现的类型的所有值:浮点数、整数、字符串、布尔值。
如果您的数据字段值类型存在差异,使用语法
<field_key>::<type> 查询不同的数据类型。
示例
测量 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 返回与字段键相关的每种数据类型,跨越每个分片。
示例
测量 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。
该范围之外的时间戳返回一个 parsing error。
我怎么知道字段中存储的数据类型是什么?
查询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> 语法支持将字段值从整数转换为浮点数或从浮点数转换为整数。请参见 Cast Operations 获取示例。没有方法将浮点数或整数转换为字符串或布尔值(反之亦然)。
我们在下面列出了更改字段数据类型的可能解决方法。请注意,这些解决方法不会更新已经写入数据库的数据。
将数据写入不同的字段
最简单的解决方法是开始将新数据类型写入同一系列中的不同字段。
处理分片系统
字段值类型在一个 分片内不能不同,但可以在 分片之间不同。
希望更改字段数据类型的用户可以使用 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 中,纪元 0 (1970-01-01T00:00:00Z) 通常被用作空时间戳的替代。如果您请求一个没有时间戳返回的查询,例如一个时间范围无限制的聚合函数,InfluxDB 将返回纪元 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 数据库的预设时间桶或用户指定的 offset interval。
示例
预设时间桶
以下查询计算了在下午6:15到下午7:45之间的sunflowers的平均值,并将这些平均值分组为每小时的时间间隔:
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
偏移区间
以下查询计算了在6:15pm和7:45pm之间的sunflowers的平均值,并将这些平均值按一小时的间隔进行分组。它还将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测量,你会看到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
我在查询中何时应使用单引号,何时应使用双引号?
字符串值使用单引号(例如,标签值),但标识符(数据库名称、保留策略名称、用户名、测量名称、标签键和字段键)则不使用单引号。
如果标识符以数字开头,包含除 [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"
有关查询中时间语法的更多信息,请参见 Data Exploration。
为什么在创建新的默认保留策略后我会丢失数据?
当您在数据库上创建一个新的 DEFAULT 保留策略(RP)时,写入旧的 DEFAULT RP 的数据将保留在旧 RP 中。未指定 RP 的查询会自动查询新的 DEFAULT RP,因此旧数据可能会显示为缺失。要查询旧数据,您必须在查询中完全限定相关数据。
示例:
所有测量中的数据 fleeting 都属于名为 DEFAULT 的 RP,称为 one_hour:
> SELECT count(flounders) FROM fleeting
name: fleeting
--------------
time count
1970-01-01T00:00:00Z 8
我们 create 一个新的 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 覆盖之前通过标签区分的 points。在所有 INTO 查询中包含 GROUP BY * 以保留新写入数据中的标签。
请注意,这种行为不适用于使用 TOP() 或 BOTTOM() 函数的查询。有关更多信息,请参阅 TOP() 和 BOTTOM() 文档。
示例
初始数据
这个 french_bulldogs 测量包括 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 点是重复的点,并将 nugget 点用 rumple 点覆盖。
> 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查询
一个 INTO 查询与 GROUP BY * 子句将 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
我如何跨测量查询数据?
当前,没有办法进行跨测量的数学运算或分组。所有数据必须在单个测量下才能一起查询。InfluxDB 不是关系型数据库,跨测量映射数据目前不是推荐的 schema。请参见 GitHub 问题 #3552,讨论在 InfluxDB 中实现 JOIN 的问题。
时间戳的顺序重要吗?
编号 我们的测试表明,InfluxDB 完成以下查询所需的时间之间几乎没有差异:
SELECT ... FROM ... WHERE time > 'timestamp1' AND time < 'timestamp2'
SELECT ... FROM ... WHERE time < 'timestamp2' AND time > 'timestamp1'
如何选择没有值的标签的数据?
指定一个空的标签值为 ''。例如:
> 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 如何处理重复数据点?
一个点通过测量名称、tag set 和时间戳唯一标识。如果您提交一个与现有点具有相同测量、标签集和时间戳的新点,则字段集成为旧字段集和新字段集的并集,其中任何冲突归于新的字段集。这是预期的行为。
例如:
旧点: 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 关键字作为标识符,则需要对该标识符进行双引号处理。这可能会导致不直观的错误。标识符包括连续查询名称、数据库名称、字段键、度量名称、保留策略名称、订阅名称、标签键和用户名。
时间
关键词 time 是一个特殊情况。
time 可以是一个
连续查询 名称、
数据库名称、
测量 名称、
保留策略 名称、
订阅 名称,以及
用户 名称。
在这些情况下,time 在查询中不需要双引号。
time 不能是 字段键 或
标签键;
InfluxDB 拒绝将 time 作为字段键或标签键的写入,并返回错误。
示例
将 time 作为一个度量并查询它
> INSERT time value=1
> SELECT * FROM time
name: time
time value
---- -----
2017-02-07T18:28:27.349785384Z 1
time 是 InfluxDB 中有效的测量名称。
将 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。
字符
为了保持正则表达式和引号的简单,避免在标识符中使用以下字符:
\ 反斜杠
^ 抑扬符
$ 美元符号
' 单引号
" 双引号
= 等号
, 逗号
我什么时候应该使用单引号,什么时候应该使用双引号来写数据?
在通过行协议写入数据时,避免使用单引号和双引号来引用标识符;请参见以下示例,以了解如何引用带引号的标识符会使查询变得复杂。标识符是数据库名称、保留策略名称、用户名、度量名称、标签键和字段键。
使用双引号的测量写入:
INSERT "bikes" bikes_available=3适用查询:SELECT * FROM "\"bikes\""使用单引号的测量写入:
INSERT 'bikes' bikes_available=3适用查询:SELECT * FROM "\'bikes\'"写入未引用的测量值:
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"
有关更多信息,请参见 Line protocol。
时间戳的精度重要吗?
是的。 为了最大化性能,在将数据写入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'
权衡的结果是,具有重复时间戳的相同点,更可能在精度降低时发生,可能会覆盖其他点。
编写稀疏历史数据的配置建议和模式指南是什么?
对于想将稀疏的历史数据写入InfluxDB的用户,InfluxData建议:
首先,将您的 保留策略 的 分片组 持续时间延长到几年的时间。 默认的分片组持续时间为一周,如果您的数据覆盖了几百年——那么,这就是很多的分片! 拥有极高数量的分片对 InfluxDB 来说效率低下。 使用 ALTER RETENTION POLICY 查询 增加您数据的保留策略的分片组持续时间。
其次,临时降低cache-snapshot-write-cold-duration配置设置。如果您正在写入大量历史数据,默认设置(10m)可能会导致系统在每个分片中将所有数据保留在缓存中。临时将cache-snapshot-write-cold-duration设置降低到10s,在您写入历史数据时使该过程更加高效。
我在哪里可以找到InfluxDB Enterprise日志?
在systemd操作系统上,可以使用journalctl命令访问服务日志。
元数据: journalctl -u influxdb-meta
数据 : journalctl -u influxdb
企业控制台: journalctl -u influx-enterprise
journalctl 的输出可以被重定向以将日志打印到文本文件中。使用systemd,日志的保留取决于系统的journald设置。
为什么在我的元节点日志中看到503 Service Unavailable错误?
如果您还没有将元节点加入集群,这是预期的行为。 一旦您 将元节点加入集群,503 错误应该停止出现在日志中。
为什么我在一些数据节点日志中看到409错误?
当您在集群上创建一个
连续查询 (CQ)
时,每个数据节点将请求CQ租约。
只有一个数据节点可以接受租约。
该数据节点的日志中将有一个200。
所有其他数据节点将被拒绝租约,并在其日志中有一个409。
这是预期的行为。
被拒绝租赁的数据节点的日志输出:
[meta-http] 2016/09/19 09:08:53 172.31.4.132 - - [19/Sep/2016:09:08:53 +0000] GET /lease?name=continuous_querier&node_id=5 HTTP/1.2 409 105 - InfluxDB Meta Client b00e4943-7e48-11e6-86a6-000000000000 380.542µs
接受租约的数据节点的日志输出:
[meta-http] 2016/09/19 09:08:54 172.31.12.27 - - [19/Sep/2016:09:08:54 +0000] GET /lease?name=continuous_querier&node_id=0 HTTP/1.2 200 105 - InfluxDB Meta Client b05a3861-7e48-11e6-86a7-000000000000 8.87547ms
为什么在我的数据节点日志中会看到 hinted handoff queue not empty 错误?
[write] 2016/10/18 10:35:21 write failed for shard 2382 on node 4: hinted handoff queue not empty
此错误仅为信息性错误,并不一定表示集群中存在问题。它表示正在处理写入请求的节点当前在其本地 hinted handoff 队列中有目标节点的数据。协调节点在目标节点的提示交接队列完全排空之前不会尝试直接写入其他节点。新数据被追加到提示交接队列中。这有助于数据按时间顺序到达,以确保图表和警报的一致性,并且还防止数据节点之间不必要的连接尝试失败。在提示交接队列为空之前,该消息将继续在日志中显示。使用 ls -lRh /var/lib/influxdb/hh 监控提示交接队列的大小,以确保它们在减少。
请注意,对于某些 写一致性 设置,InfluxDB 可能会在写入尝试时返回写入错误 (500),即使这些点已经成功排入提示交接队列。一些写入客户端可能会尝试重新发送这些点,从而导致重复的点被添加到提示交接队列中,并延长队列排空所需的时间。如果队列未能排空,请考虑暂时降低写入一致性设置,或暂停写入客户端的重试,直到提示交接队列完全排空。
为什么我在数据节点日志中看到 error writing count stats ...: partial write 错误?
[stats] 2016/10/18 10:35:21 error writing count stats for FOO_grafana: partial write
_internal_ 数据库收集每个节点以及整个 InfluxDB 企业集群的集群信息。集群指标使用 consistency=all 复制到其他节点。对于 写一致性 为 all,InfluxDB 在写入尝试时即使点成功排队在提示交接中,也会返回写入错误 (500)。因此,如果仍然有点在提示交接中,_internal_ 写入将失败一致性检查并记录错误,尽管数据在持久化提示交接队列中并最终应该持久化。
为什么我的数据节点日志中会看到 queue is full 错误?
此错误表示接收写入的协调节点无法将传入的写入添加到目标节点的提示交接队列中,因为这将超过队列的最大大小。此错误通常表示集群发生了灾难性条件 - 一个数据节点可能已离线或无法在较长时间内接受写入。
控制配置设置位于文件的 [hinted-handoff] 部分。 max-size 是每个提示交接队列的总大小(以字节为单位)。 当超过 max-size 时,该节点的所有新写入都会被拒绝,直到队列大小降到 max-size 以下。 max-age 是一个点在队列中存留的最长时间。 一旦达到这个限制,点将从队列中过期。 年龄是从点的写入时间计算的,而不是点的时间戳。
为什么我在尝试使用 influxd-ctl join 添加元节点时会看到 unable to determine if "hostname" is a meta node?
元节点使用 /status 接口来确定另一个元节点的当前状态。一个健康的元节点,如果准备好加入集群,将会以 200 HTTP 响应代码和以下格式的 JSON 字符串进行响应(假设使用默认端口):
"nodeType":"meta","leader":"","httpAddr":"
如果您在尝试 influxd-ctl join 一个新的元节点时收到错误信息,这意味着从 /status 端点返回的 JSON 字符串不正确。这通常表示元节点配置文件不完整或不正确。使用 curl -v "http:// 检查 HTTP 响应,并确保 hostname、bind-address 和 http-bind-address 正确填写。还要检查元节点配置文件中的 license-key 或 license-path。最后,确保在 join 命令中指定 http-bind-address 端口,例如 influxd-ctl join hostname:8091。
为什么当我的系统有空闲内存时,InfluxDB 报告内存不足 (OOM) 异常?
mmap 是一个将文件映射到内存的Unix系统调用。
随着InfluxDB Enterprise集群中分片数量的增加,内存映射的数量也随之增加。
如果映射数量超过配置的最大限制,该节点将报告内存不足。
要检查当前 influxd 进程使用的映射数量:
wc -l /proc/$(pidof influxd)/maps
该 max_map_count 文件包含一个进程可以拥有的最大内存映射区域数。 默认限制是 65536。 我们建议通过运行以下命令将其增加到 262144(默认值的四倍):
echo vm.max_map_count=262144 > /etc/sysctl.d/90-vm.max_map_count.conf
要使更改永久生效:
sysctl --system
重新启动 influxd 进程,并在集群中的每个节点上重复此操作。