行协议教程
TSDB For InfluxDB®的行协议(Line Protocol)是一种基于文本的格式,用于将数据点写入数据库。数据点必须符合行协议格式,TSDB For InfluxDB®才能成功解析和写入数据点。
语法
行协议中,一行数据表示TSDB For InfluxDB®中的一个数据点,它告诉TSDB For InfluxDB®该数据点的measurement、tag set、field set和时间戳。以下代码块展示了行协议的一个示例,并将其分解成多个组成部分:
weather,location=us-midwest temperature=82 1465839830100400200
| -------------------- -------------- |
| | | |
| | | |
+-----------+--------+-+---------+-+---------+
|measurement|,tag_set| |field_set| |timestamp|
+-----------+--------+-+---------+-+---------+
下面,我们将逐个分析上图中的元素。
Measurement
您想要写入数据的measurement的名字。在行协议中,measurement是必须要有的。在上面的示例中,measurement的名字是weather
。
Tag set
您想要在数据点中包含的tag。在行协议中,tag是可选的。请注意,measurement和tag set被逗号隔开并且它们之间没有空格。
使用等号=
分隔tag key和tag value,并且它们之间不能有空格:
<tag_key>=<tag_value>
使用逗号分隔多个tag key-value pairs,并且它们之间不能有空格:
<tag_key>=<tag_value>,<tag_key>=<tag_value>
在示例中,tag set由一个tag组成:location=us-midwest
。在示例中添加另一个tag(season=summer
),如下所示:
weather,location=us-midwest,season=summer temperature=82 1465839830100400200
为了获得最佳性能,您应该在将数据点发送到数据库之前,将tag按tag key进行排序。排序结果应该与Go bytes.Compare function的结果匹配。
空格 I
使用空格分隔measurement和field set,如果数据点中包含了tag set,也需要使用空格分隔tag set和field set。在行协议中,这里必须使用空格。
没有tag set的有效行协议:
weather temperature=82 1465839830100400200
Field set
数据点中的field。在行协议中,每个数据点至少需要有一个field。
使用等号=
分隔field key和field value,并且它们之间不能有空格:
<field_key>=<field_value>
使用逗号分隔多个field key-value pairs,并且它们之间不能有空格:
<field_key>=<field_value>,<field_key>=<field_value>
在示例中,field set由一个field组成:temperature=82
。在示例中添加另一个field(humidity=71
),如下所示:
weather,location=us-midwest temperature=82,humidity=71 1465839830100400200
空格 II
使用空格分隔field set和时间戳(如果有的话)。如果为数据点指定了时间戳,那么在行协议中,这里必须使用空格。
时间戳
数据点中的时间戳是精确到纳米的Unix时间。在行协议中,时间戳是可选的。如果您没有指定数据点的时间戳,那么TSDB For InfluxDB®使用服务器本地的纳秒级时间戳(UTC格式)作为数据点的时间戳。
在示例中,时间戳是1465839830100400200
(也就是2016-06-13T17:43:50.1004002Z
,按照RFC3339格式)。下面的行协议表示相同的数据点,但是不带时间戳。当TSDB For InfluxDB®将该数据点写入数据库,它使用服务器的本地时间戳,而不是2016-06-13T17:43:50.1004002Z
。
weather,location=us-midwest temperature=82
使用HTTP API来指定除纳秒之外其它精度的时间戳,例如微秒、毫秒或者秒。我们建议尽量使用最粗糙的精度,因为这可以显著提高压缩效果。
请使用网络时间协议(Network Time Protocol,NTP)来同步主机(host)之间的时间。TSDB For InfluxDB®使用主机的本地UTC时间为数据分配时间戳;如果主机的时钟与NTP不同步,写入TSDB For InfluxDB®的数据的时间戳可能会不准确。
数据类型
本节将介绍行协议中主要组成部分的数据类型:measurement、tag key、tag value、field key、field value和时间戳。
measurement、tag key、tag value和field key始终是字符串。
注释:因为TSDB For InfluxDB®将tag value存储为字符串,所以TSDB For InfluxDB®不能对tag value执行数学运算。此外,InfluxQL函数不接受将tag value作为主要参数。当您在设计schema时,最好考虑一下这些细节。
时间戳是UNIX时间戳。最小的有效时间戳是-9223372036854775806
或1677-09-21T00:12:43.145224194Z
,最大的有效时间戳是9223372036854775806
或2262-04-11T23:47:16.854775806Z
。如上所述,默认情况下,TSDB For InfluxDB®假设时间戳精确到纳秒。关于如何指定其它精度,请查看文档HTTP API。
field value可以是浮点数、整数、字符串或者布尔值:
浮点数 - 默认情况下,TSDB For InfluxDB®假设所有数值类型的field value是浮点数。
将field value
82
存储为浮点数:weather,location=us-midwest temperature=82 1465839830100400200
整数 - 在field value后面加上
i
,告诉TSDB For InfluxDB®将该数字存储为整数。将field value
82
存储为整数:weather,location=us-midwest temperature=82i 1465839830100400200
字符串 - 用双引号把字符串类型的field value括起来(更多关于行协议中引号的介绍,请参见“引号”内容)。
将field value
too warm
存储为字符串:weather,location=us-midwest temperature="too warm" 1465839830100400200
布尔值 - 可以使用
t
、T
、true
、True
或TRUE
指定TRUE,使用f
、F
、false
、False
或FALSE
指定FALSE。将field value
true
存储为布尔值:weather,location=us-midwest too_hot=true 1465839830100400200
说明注释:写入和查询布尔值的语法不一样。请查看FAQ获得更多相关信息。
在measurement中,一个field的数据类型在一个shard内不会不一致,但是在不同的shard,它的数据类型可以不同。例如,如果TSDB For InfluxDB®尝试将整数存储在与浮点数相同的shard中,那么将整数写入一个之前接受浮点数的field会失败:
> INSERT weather,location=us-midwest temperature=82 1465839830100400200
> INSERT weather,location=us-midwest temperature=81i 1465839830100400300
ERR: {"error":"field type conflict: input field \"temperature\" on measurement \"weather\" is type int64, already exists as type float"}
但是,如果TSDB For InfluxDB®尝试将整数存储在一个新的shard中,那么将整数写入一个之前接受浮点数的field会成功:
> INSERT weather,location=us-midwest temperature=82 1465839830100400200
> INSERT weather,location=us-midwest temperature=81i 1467154750000000000
>
若想了解field value的数据类型差异如何影响SELECT *
查询,请查看FAQ的相关章节。
引号
本节将介绍在行协议中,什么时候不能使用双引号("
)或单引号('
),什么时候应该使用它们。我们先介绍不使用引号的情形,然后再介绍使用引号的情形:
不能用双引号或单引号将时间戳括起来。这是无效的行协议。
示例:
> INSERT weather,location=us-midwest temperature=82 "1465839830100400200" ERR: {"error":"unable to parse 'weather,location=us-midwest temperature=82 \"1465839830100400200\"': bad timestamp"}
不能用单引号将field value括起来(即使它们是字符串)。这也是无效的行协议。
示例:
> INSERT weather,location=us-midwest temperature='too warm' ERR: {"error":"unable to parse 'weather,location=us-midwest temperature='too warm'': invalid boolean"}
不能用双引号或单引号将measurement的名字、tag key、tag value和field key括起来。虽然这是有效的行协议,但是TSDB For InfluxDB®会把引号当作是名字的一部分。
示例:
> INSERT weather,location=us-midwest temperature=82 1465839830100400200 > INSERT "weather",location=us-midwest temperature=87 1465839830100400200 > SHOW MEASUREMENTS name: measurements ------------------ name "weather" weather
查询在
"weather"
中的数据,您需要用引号将measurement的名字括起来,并且将measurement中的双引号转义:> SELECT * FROM "\"weather\"" name: "weather" --------------- time location temperature 2016-06-13T17:43:50.1004002Z us-midwest 87
不能用双引号将字符串类型、整型或布尔类型的field value括起来。否则,TSDB For InfluxDB®会把这些值当作字符串。
示例:
> INSERT weather,location=us-midwest temperature="82" > SELECT * FROM weather WHERE temperature >= 70 >
需要用双引号将字符串类型的field value括起来。
示例:
> INSERT weather,location=us-midwest temperature="too warm" > SELECT * FROM weather name: weather ------------- time location temperature 2016-06-13T19:10:09.995766248Z us-midwest too warm
特殊字符和关键字
特殊字符
对于tag key、tag value和field key,始终使用反斜杠\
来转义:
逗号
,
weather,location=us\,midwest temperature=82 1465839830100400200
等号
=
weather,location=us-midwest temp\=rature=82 1465839830100400200
空格
weather,location\ place=us-midwest temperature=82 1465839830100400200
对于measurement,始终使用反斜杠
\
来转义:逗号
,
wea\,ther,location=us-midwest temperature=82 1465839830100400200
空格
wea\ ther,location=us-midwest temperature=82 1465839830100400200
对于字符串类型的field value,使用反斜杠
\
来转义:双引号
"
weather,location=us-midwest temperature="too\"hot\"" 1465839830100400200
行协议不需要用户将反斜杠\
转义,但是如果您这样做也没有问题。例如,写入以下数据:
weather,location=us-midwest temperature_str="too hot/cold" 1465839830100400201
weather,location=us-midwest temperature_str="too hot\cold" 1465839830100400202
weather,location=us-midwest temperature_str="too hot\\cold" 1465839830100400203
weather,location=us-midwest temperature_str="too hot\\\cold" 1465839830100400204
weather,location=us-midwest temperature_str="too hot\\\\cold" 1465839830100400205
weather,location=us-midwest temperature_str="too hot\\\\\cold" 1465839830100400206
将会理解为(请注意,用单引号或双引号将反斜杠括起来会产生相同的结果):
> SELECT * FROM "weather"
name: weather
time location temperature_str
---- -------- ---------------
1465839830100400201 us-midwest too hot/cold
1465839830100400202 us-midwest too hot\cold
1465839830100400203 us-midwest too hot\cold
1465839830100400204 us-midwest too hot\\cold
1465839830100400205 us-midwest too hot\\cold
1465839830100400206 us-midwest too hot\\\cold
所有其它的特殊字符也不需要转义。例如,行协议处理表情符号(emojis)没有问题:
> INSERT we⛅️ther,location=us-midwest t⛅️emperture=82 1465839830100400200
> SELECT * FROM "we⛅️ther"
name: we⛅️ther
------------------
time location t⛅️emperture
1465839830100400200 us-midwest 82
关键字
行协议将InfluxQL关键字作为标识符名字。通常,我们建议避免在schema中使用InfluxQL关键字,因为它可能会在查询数据时引起混淆。
关键字time
是一个特例。time
可以是一个连续查询名字、数据库名字、measurement的名字、保留策略名字、subscription的名字和用户名。在这些情况下,不需要在查询中用双引号将time
括起来。time
不能是field key或tag key;TSDB For InfluxDB®拒绝写入将time
作为field key或tag key的数据,对于这种数据写入,TSDB For InfluxDB®会返回错误。请查阅FAQ获得更多相关信息。
将数据写入TSDB For InfluxDB®
将数据写入数据库
现在您已经知道了关于行协议的所有内容,那么如何使用行协议将数据写入TSDB For InfluxDB®呢?在本节,我们将给出两个简单示例,请参见工具章节获取更多相关信息。
HTTP API
使用HTTP API将数据写入TSDB For InfluxDB®。向/write
路径发送POST
请求,并在request body中给出行协议数据:
curl -i -XPOST "https://<网络地址>:3242/write?db=science_is_cool&u=<账号名称>&p=<密码>" --data-binary 'weather,location=us-midwest temperature=82 1465839830100400200'
有关查询参数、状态码、响应和更多示例的深入讲解,请查看文档HTTP API。
CLI
使用TSDB For InfluxDB®的命令行界面(Command Line Interface,CLI)将数据写入TSDB For InfluxDB®。启动CLI,使用相关的数据库,并且将INSERT
放在行协议语句前面:
INSERT weather,location=us-midwest temperature=82 1465839830100400200
您还可以使用CLI导入文件中的数据。
将数据写入TSDB For InfluxDB®的方法有几种,请参见工具章节获取更多相关信息。
重复数据点
measurement的名字、tag set和时间戳唯一标识一个数据点。如果您提交的数据具有相同measurement、tag set和时间戳但具有不同field set,那么数据的field set会变为旧field set和新field set的并集,如果有任何冲突以新field set为准。
有关此行为的完整示例和如何避免这种情况,请查看FAQ相关章节。