FAQ
本页面讨论了经常容易混淆的内容,以及跟其它数据库系统相比TSDB For InfluxDB®以意想不到的方式运行的地方。
问题导览
管理(Administration)
序列和序列基数
数据查询
数据写入
命令行界面(Influx CLI)
数据类型
InfluxQL函数
管理(Administration)
如何高效安全地删除数据?
InfluxDB的drop measurement 、drop series、delete采用逻辑删除,该删除方式有以下几点缺陷:
InfluxDB 1.X在代码实现层面存在死锁的可能性。
查询需要过滤被删除的时间线,严重影响查询效率。
逻辑删除无法立刻释放磁盘空间,需要等待后台数据合并调度,空间释放慢。
建议通过修改数据保留策略来删除老数据,或使用drop shard或drop database进行物理删除。
为什么修改保留策略后不生效?
在v1.8.13及以后版本,修改保留策略后立即生效,若没有生效请检查以下两点:
版本是否为v1.8.12或更老的版本,老版本中修改保留策略需要等待后台调度,请耐心等待30~60分钟。
Shard覆盖的时间范围较大,可以通过
show shards
查看,只有当前时间超过Shard的结束时间时,该Shard才可以被删除。
为什么服务经常中断?
检查内存水位是否比较高,一般内存水位超过80%以上,可能会出现内存上涨导致的进程OOM,建议对实例进行升配。
内存占用为什么很高?
内存占用高主要有以下几点原因:
时间线数量多。索引合并时会占用大量内存,请排查schema设计是否合理,不建议存储超过100W的时间线。海量时间线场景详情,请参见Lindorm 时序引擎简介。
数据量大。数据量越大,空间占用越多,数据文件合并也会占用大量内存,而且重启花费的时间也会比较长。大量数据存储场景详情,请参见Lindorm 时序引擎简介。
存在大查询。避免使用大查询,建议查询时候带上 tag 和时间过滤,减少数据扫描的范围。
如果有使用Grafana查询,Grafana在配置图表时可能会下发
show tag keys
的查询,此类查询会瞬间占用过多的内存导致进程OOM。推荐升级到v1.8.13后,可以配置禁用show tag keys
的查询。
当内存水位超过80%以上时,建议对实例进行升配。升配操作详情,请参见升配或降配。
云盘扩容是否会重启?
InfluxDB云盘扩容时进程会重启。如果是单机版本,重启期间可能会导致服务的不可用。如果是高可用版本,三节点会滚动重启,业务一般不会受到影响。
重启需要多长时间?
InfluxDB 重启时间和存储的数据量有关,一般存储的数据量越大,重启所需的时间越长。
是否支持InfluxDB内置的Grafana?
建议使用阿里云产品可观测可视化 Grafana 版。不建议使用InfluxDB内置的Grafana,因为InfluxDB内置的Grafana版本比较旧而且不再维护更新。
为什么访问出现ip block
错误?
v1.8.12及以下版本会在错误密码重试太多时临时禁用IP,建议升级到v1.8.13及以上版本。
如何识别TSDB For InfluxDB®的版本?
有多种方法可以识别您正在使用的TSDB For InfluxDB®版本:
curl路径/ping
$ curl -i 'https://<网络地址>:3242/ping?u=<账号名称>&p=<密码>' HTTP/1.1204NoContent Content-Type: application/json X-Influxdb-Build: OSS X-Influxdb-Version:1.7.x
启动TSDB For InfluxDB®的命令行界面
$ influx -ssl -username <账号名称>-password <密码>-host <网络地址>-port 3242 Connected to https://<网络地址>:3242 version 1.7.x
Shard Group Duration和保留策略之间的关系是什么?
TSDB For InfluxDB®将数据存储在Shard Group。一个Shard Group覆盖一个特定的时间间隔;TSDB For InfluxDB®通过查看相关保留策略(Retention Policy)的DURATION
来确定时间间隔。下表列出了RP的DURATION
和一个Shard Group的时间间隔之间的默认关系:
RP持续时间(duration) | Shard Group时间间隔 |
< 2 days | 1 hour |
>= 2 days and <= 6 months | 1 day |
> 6 months | 7 days |
使用SHOW RETENTION POLICIES
查看保留策略的Shard Group Duration。
当更改保留策略后,为什么数据没有丢失?
有可能是以下原因,导致保留策略改变后数据没有马上丢失:
第一个可能的原因(最有可能的场景):默认情况下,TSDB For InfluxDB®每30分钟检查并强制执行一次RP。您可能需要等到下一次RP检查,TSDB For InfluxDB®才能删除在RP的新
DURATION
之外的数据。第二个可能的原因:更改RP的
DURATION
和SHARD DURATION
会导致意外的数据保留。TSDB For InfluxDB®将数据存储在Shard Group,每个Shard Group覆盖一个特定的RP和时间间隔。当TSDB For InfluxDB®强制执行RP时,整个Shard Group的数据会被删除,而不是单个数据点。TSDB For InfluxDB®不能拆分Shard Group。如果RP的新DURATION
小于旧的SHARD DURATION
,并且TSDB For InfluxDB®正在将数据写入一个旧的、DURATION
较长的Shard Group,那么系统将强制把所有数据存储在该Shard Group中,即使该Shard Group中有些数据已经在新的DURATION
之外。一旦Shard Group中所有数据都在新的DURATION
之外,TSDB For InfluxDB®将会删除整个Shard Group,然后系统开始将数据写入具有新的、更短SHARD DURATION
的Shard Group,避免进一步意想不到的数据保留。
为什么TSDB For InfluxDB®无法解析微秒单位?
在不同场景下写入、查询以及在TSDB For InfluxDB®命令行界面(Influx CLI)设置精度,用于指定微秒时间单位的语法也不同。下表显示了每个类别支持的语法:
使用HTTP API写入数据 | 所有查询 | 在Influx CLI设置精度 | |
u | √ | √ | √ |
us | ❌ | ❌ | ❌ |
µ | ❌ | √ | ❌ |
µs | ❌ | ❌ | ❌ |
序列和序列基数
为什么序列基数很重要?
TSDB For InfluxDB®维护系统中每个序列在内存中的索引。随着序列数量不断增加,RAM(内存)使用量也在不断增加。序列基数过大会导致操作系统终止TSDB For InfluxDB®进程,并抛出内存不足(OOM)异常。请查看文档InfluxQL参考了解关于序列基数的InfluxQL命令。
如何进行建模,有什么注意事项?
不建议存储大量时间线,建议时间线量级保持在100w以下,海量时间线场景建议使用Lindorm 时序引擎简介。其次,开始建模前请先参考InfluxDB 建模指南。虽然InfluxDB会对tag创建索引来加速查询,但是过多的tag会因时间线膨胀而导致查询/写入速度降低,因此在建模上需要注意控制时间线的数量,特别是以下几点:
避免使用id、hash值和时间等极易无限膨胀的值作为tag。
避免在measurement和tag的命名中存储数据信息,请将相关信息保存到tag或field中。
避免在一个tag中存储多个信息,可以拆解成多个tag。
需要经常使用Group by字段,可以当作tag来建模。
数据查询
如何排查慢查询的原因?
慢查询一般是由于扫描了过多时间线或原始数据导致,因此,建议为每个查询都加上tag过滤条件和时间范围过滤条件。此外可以使用EXPLAIN ANALYZE命令查看自查与优化查询,execution_time主要包括原始数据读取时间和计算时间,planning_time主要包括时间线扫描时间,可以针对这两个时间优化查询过滤条件。
什么决定了GROUP BY time()
查询返回的时间间隔?
GROUP BY time()
查询返回的时间间隔符合TSDB For InfluxDB®的预设时间段或者符合用户指定的偏移间隔。示例如下:
预设时间段
以下查询计算
sunflowers
在6:15pm到7:45pm之间的平均值,并将这些平均值按一小时进行分组:SELECT mean("sunflowers") FROM "flower_orders" WHERE time >='2016-08-29T18:15:00Z' AND time <='2016-08-29T19:45:00Z' GROUP BY time(1h)
下面的结果展示了TSDB For InfluxDB®如何维护它的预设时间段。
在这个示例中,6pm是一个预设的时间段,7pm也是一个预设的时间段。由于
WHERE
子句中指定了查询的时间范围,所以在计算6pm时间段对应的平均值时不包括在6:15pm之前的数据,但是用于计算6pm时间段平均值的数据必须发生在6pm这个小时里。对于7pm时间段也是一样;用于计算7pm时间段平均值的数据必须发生在7pm这个小时里。虚线部分展示了用于计算每个平均值的数据点。请注意,虽然结果中第一个时间戳是
2016-08-29T18:00:00Z
,但是在该时间段的查询结果不包含发生在2016-08-29T18:15:00Z
(WHERE
子句中指定的开始时间)之前的数据。原始数据结果:
name: flower_orders name: flower_orders —————————------------------- time sunflowers time mean 2016-08-29T18:00:00Z342016-08-29T18:00:00Z22.332 |--|2016-08-29T19:00:00Z62.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:00Z70
偏移间隔
以下查询计算
sunflowers
在6:15pm到7:45pm之间的平均值,并将这些平均值按一小时进行分组,同时,该查询还将TSDB For 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
在这个示例中,用户指定的偏移间隔将TSDB For InfluxDB®的预设时间段前移了
15
分钟。现在,6pm时间段的平均值包括在6:15pm和7:15pm之间的数据,7pm时间段的平均值包括在7:15pm和8:15pm之间的数据。虚线部分展示了用于计算每个平均值的数据点。请注意,现在结果中第一个时间戳是
2016-08-29T18:15:00Z
,而不是2016-08-29T18:00:00Z
。原始数据结果:
name: flower_orders name: flower_orders —————————------------------- time sunflowers time mean 2016-08-29T18:00:00Z342016-08-29T18:15:00Z30.75 |--|2016-08-29T19:15:00Z65 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| |--|
为什么查询没有返回任何数据或者只返回一部分数据?
对于为什么查询没有返回任何数据或者只返回一部分数据,有几种可能的解释。我们在下面列出了一些最常见的原因:
保留策略
第一个也是最常见的解释与保留策略(RP)有关。TSDB For InfluxDB®自动从数据库的默认(
DEFAULT
)RP中查询数据。如果您的数据不是存储在默认的RP,TSDB For InfluxDB®不会返回任何结果,除非您明确指定所使用的RP。SELECT子句中的tag key
在
SELECT
子句中,至少需要包含一个field key,查询才会返回数据。如果SELECT
子句只包含一个或多个tag key,查询会返回空的结果。请查看文档数据探索获得更多相关信息。查询时间范围
另一个可能的解释与查询的时间范围有关。默认情况下,大多数
SELECT
查询涵盖在1677-09-21 00:12:43.145224194
UTC和2262-04-11T23:47:16.854775806Z
UTC之间的时间范围。SELECT
查询还包括GROUP BY time()
子句,但是,它涵盖的时间范围在1677-09-21 00:12:43.145224194
和now()
之间。如果您的数据发生在now()
之后,那么GROUP BY time()
查询不会覆盖这些发生在now()
之后的数据。如果查询语句包括GROUP BY time()
子句,并且有数据发生在now()
之后,您需要为时间范围提供一个上限。标识符名字
最后一个常见的解释与Schema有关(field和tag有相同的名字)。如果field key和tag key相同,那么在所有查询中优先考虑field。在查询中,你需要使用
::tag
语法指定tag key。
为什么GROUP BY time()
查询不返回发生在now()
之后的时间戳?
大多数SELECT
语句的默认时间范围在1677-09-21 00:12:43.145224194 UTC
和2262-04-11T23:47:16.854775806Z UTC
之间。对于带GROUP BY time()
子句的SELECT
语句,默认的时间范围在1677-09-21 00:12:43.145224194
和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)
>
请查看数据探索获得更多关于时间语法的信息。
是否可以对时间戳执行数学运算?
目前,在TSDB For InfluxDB®中,不能对时间戳执行数学运算。更多关于时间的计算必须由接收查询结果的客户端执行。
对时间戳使用InfluxQL函数,TSDB For InfluxDB®仅提供有限的支持。ELAPSED()函数返回单个field中时间戳之间的差值。
是否可以从返回的时间戳中识别写入精度?
不管提供的写入精度是多少,TSDB For InfluxDB®将所有时间戳存储为纳秒。需要注意的一个重要事项是,当返回查询结果时,数据库会不动声色地删除时间戳后面的零,使原始的写入精度很难识别。
在下面的示例中,tag precision_supplied
和timestamp_supplied
分别显示了用户在写入数据时提供的时间精度和时间戳。因为TSDB For InfluxDB®默默地将返回的时间戳后面的零删除了,所以从返回的时间戳中很难识别写入精度。
name: trails
-------------
time value precision_supplied timestamp_supplied
1970-01-01T01:00:00Z3 n 3600000000000
1970-01-01T01:00:00Z5 h 1
1970-01-01T02:00:00Z4 n 7200000000000
1970-01-01T02:00:00Z6 h 2
当查询数据时,什么时候应该使用单引号,什么时候应该使用双引号?
用单引号将字符串类型的值括起来(例如:tag value),但是不要用单引号将标识符(数据库名字、保留策略名字、用户名、measurement的名字、tag key和field key)括起来。
如果标识符以数字开头,或包含除[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'
用单引号将日期时间字符串括起来。如果您使用双引号将日期时间字符串括起来,TSDB For 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
)保留策略后会丢失数据?
当您在数据库中创建一个新的默认保留策略(RP)后,在旧的默认RP中的数据依旧保存在旧的RP中。对于不指定RP的查询,将会自动查询新默认RP中的数据,所有旧数据可能会丢失。为了查询旧数据,必须完全限定查询中的数据。示例如下:
在measurement fleeting
中的所有数据属于默认的RP,该RP的名字为one_hour
:
> SELECT count(flounders) FROM fleeting
name: fleeting
--------------
time count
1970-01-01T00:00:00Z8
现在我们创建一个新的默认RP(two_hour
),并执行相同的查询:
> SELECT count(flounders) FROM fleeting
>
为了查询旧数据,我们必须通过完全限定fleeting
来指定旧的默认RP:
> SELECT count(flounders) FROM fish.one_hour.fleeting
name: fleeting
--------------
time count
1970-01-01T00:00:00Z8
为什么带有WHERE OR
时间子句的查询返回空结果?
目前,TSDB For InfluxDB®不支持在WHERE
子句中使用OR
来指定多个时间范围。如果查询中的WHERE
子句使用OR
来指定多个时间范围,那么TSDB For InfluxDB®不会返回任何结果。
示例:
> SELECT * FROM "absolutismus" WHERE time ='2016-07-31T20:07:00Z' OR time ='2016-07-31T23:07:17Z'
>
为什么fill(previous)
返回空结果?
如果前一个值在查询的时间范围之外,那么fill(previous)
不会填充该时间段的值。
在下面的示例中,TSDB For 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:00Z3
2016-07-12T16:50:10Z2
2016-07-12T16:50:40Z12
2016-07-12T16:50:50Z11
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:40Z12
2016-07-12T16:51:00Z12
为什么INTO
查询会丢失数据?
默认情况下,INTO
查询将原始数据中的tag转换成新写入数据的field。这会导致TSDB For InfluxDB®覆盖之前由tag区分的数据点。在所有INTO
查询中加上GROUP BY *
,可以将tag保留在新写入的数据中。
这种方式不适用于使用TOP()
或BOTTOM()
函数的查询。请查看文档InfluxDB函数获得更多关于TOP()
和BOTTOM()
的信息。
示例数据
measurement french_bulldogs
包含一个tag color
和一个field 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
查询将tagcolor
转换成新写入数据中的field。在原始数据中,数据点nugget
和rumple
仅由tagcolor
区分。一旦color
变成field,TSDB For InfluxDB®会认为数据点nugget
和rumple
是重复的,它会用数据点rumple
将数据点nugget
覆盖。> SELECT * INTO "all_dogs" FROM "french_bulldogs" name: result ------------ time written 1970-01-01T00:00:00Z3 > 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
查询将tagcolor
保留在新写入的数据中。在这种情况下,数据点nugget
和rumple
依旧是不同的数据点,TSDB For InfluxDB®不会覆盖任何数据。> SELECT "name" INTO "all_dogs" FROM "french_bulldogs" GROUP BY * name: result ------------ time written 1970-01-01T00:00:00Z3 > 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
如何查询tag key和field key名字相同的数据?
使用语法::
指定一个key是field key还是tag key。示例数据:
> INSERT candied,almonds=true almonds=50,half_almonds=511465317610000000000
> INSERT candied,almonds=true almonds=55,half_almonds=561465317620000000000
> SELECT * FROM "candied"
name: candied
-------------
time almonds almonds_1 half_almonds
2016-06-07T16:40:10Z50 true 51
2016-06-07T16:40:20Z55 true 56
指定key是field
> SELECT * FROM "candied" WHERE "almonds"::field >51 name: candied ------------- time almonds almonds_1 half_almonds 2016-06-07T16:40:20Z55 true 56
指定key是tag
> SELECT * FROM "candied" WHERE "almonds"::tag='true' name: candied ------------- time almonds almonds_1 half_almonds 2016-06-07T16:40:10Z50 true 51 2016-06-07T16:40:20Z55 true 56
如何跨measurement查询数据?
目前,无法跨measurement执行数学运算或分组。所有数据必须在同一个measurement下,才能一起查询这些数据。TSDB For InfluxDB®不是一个关系型数据库,跨measurement映射数据目前不是一个推荐的Schema。
时间戳的顺序是否重要?
不重要。测试结果表明TSDB For InfluxDB®完成以下查询所需的时间差别非常小:
SELECT ... FROM ... WHERE time >'timestamp1' AND time <'timestamp2'
SELECT ... FROM ... WHERE time <'timestamp2' AND time >'timestamp1'
如何SELECT
有tag但没有tag value的数据?
使用''
指定一个空的tag value。例如:
> SELECT * FROM "vases" WHERE priceless=''
name: vases
-----------
time origin priceless
2016-07-20T18:42:00Z8
数据写入
行协议写入注意事项
行协议写入存在如下注意点:
在数字后面加上
i
来指定整数,如value=100i
是整数,value=100
是浮点数。只在字符串类型的field value中使用双引号,measurement、tag key、tag value和field key中的双引号将被当做名字的一部分来处理。
应该用反斜杠转义特殊字符,而不是用引号将其括起来。
为什么数据写入后,却不可见?
InfluxDB会根据保留策略丢弃过期数据,建议自查写入时间戳和保留策略中设置的TTL。
磁盘空间满导致写入失败,空间下降后写入没有恢复?
InfluxDB磁盘写满后,会导致写入失败,即使空间下降后还是会写入失败。请适当扩容或者清理数据后手动在控制台重启进程来恢复写入。
如何写入整型的field value?
当写入整数时,在field value末尾加上i
。如果您不加上i
,TSDB For InfluxDB®会把field value当作浮点数。
写入整数:value=100i
写入浮点数:value=100
。
TSDB For InfluxDB®如何处理重复数据点?
measurement的名字、tag set和时间戳唯一标识一个数据点。如果您提交的数据点跟已有的数据点相比,具有相同measurement、tag set和时间戳,但具有不同field set,那么该数据点的field set会变为旧field set和新field set的并集,如果有任何冲突以新field 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
当您提交新数据点后,TSDB For InfluxDB®使用新的field value覆盖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.247
为了存储这两个数据点,可以:
引入新的tag保证唯一性。
旧数据点:
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
将新数据点写入TSDB For 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 124.57 1970-01-15T06:56:07.89Z us_west server02 25.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
将新数据点写入TSDB For 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.57 1970-01-15T06:56:07.890000001Z us_west server02 5.24
HTTP API需要怎样的换行符?
TSDB For InfluxDB®的行协议依赖换行符(\n
,这是ASCII 0x0A
)来表示一行的结束和新的一行的开始。文件或数据使用\n
以外的换行符会导致以下错误:bad timestamp
, unable to parse
。
请注意,Windows使用回车键和换行符(\r\n
)作为换行符。
当将数据写入TSDB For InfluxDB®时,应该避免哪些文字和字符?
InfluxQL关键字
如果您使用InfluxQL关键字作为标识符,您需要在每个查询中使用双引号将该标识符括起来。如果不使用双引号,会导致错误。标识符是连续查询名字、数据库名字、field key、measurement的名字、保留策略名字、tag key和用户名。
时间
关键字
time
是一个特例。time
可以是一个连续查询名字、数据库名字、measurement的名字、保留策略名字和用户名。在这些情况下,不需要在查询中用双引号将time
括起来。time
不能是field key或tag key;TSDB For InfluxDB®拒绝写入将time
作为field key或tag key的数据,对于这种数据写入,TSDB For InfluxDB®会返回错误。示例如下:将time作为measurement,写入数据并查询它。
> INSERT time value=1 > SELECT * FROM time name: time time value --------- 2017-02-07T18:28:27.349785384Z1
在TSDB For InfluxDB®中,
time
是一个有效的measurement名字。将time作为field key,写入数据并尝试查询它
> INSERT mymeas time=1 ERR:{"error":"partial write: invalid field name: input field \"time\" on measurement \"mymeas\" is invalid dropped=1"}
在TSDB For InfluxDB®中,
time
不是一个有效的field key。系统无法写入该数据点,并且返回400
错误。将time作为tag key,写入数据并尝试查询它。
> INSERT mymeas,time=1 value=1 ERR:{"error":"partial write: invalid tag key: input tag \"time\" on measurement \"mymeas\" is invalid dropped=1"}
在TSDB For InfluxDB®中,
time
不是一个有效的tag key。系统无法写入该数据点,并且返回400
错误。
字符
为了保持简单的正则表达式和引号,避免在标识符中使用以下字符:
\
反斜杠^
尖号$
货币符号'
单引号"
双引号=
等号,
逗号。
当写入数据时,什么时候应该使用单引号,什么时候应该使用双引号?
通过行协议写入数据时,避免使用单引号和双引号将标识符括起来;请查看下面的示例,使用引号后的标识符会使查询变得复杂。标识符是连续查询名字、数据库名字、field key、measurement的名字、保留策略名字、subscription的名字、tag key和用户名。
写入带双引号的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"
用双引号将字符串类型的field value括起来。
写入:
INSERT bikes happiness="level 2"
适用的查询:SELECT * FROM "bikes" WHERE "happiness"='level 2'
应该用反斜杠转义特殊字符,而不是用引号将其括起来。
写入:
INSERT wacky va\"ue=4
适用的查询:SELECT "va\"ue" FROM "wacky"
请查看文档行协议参考获得更多相关信息。
时间戳的精度是否重要?
重要。为了最大限度地提高性能,向TSDB For InfluxDB®写入数据时尽量使用最粗糙的时间精度。
在下面两个例子中,第一个请求使用默认精度(纳秒),而第二个请求将精度设置为秒:
curl -i -XPOST "https://<网络地址>:3242/write?db=weather&u=<账号名称>&p=<密码>"--data-binary 'temperature,location=1 value=90 1472666050000000000'
curl -i -XPOST "https://<网络地址>:3242/write?db=weather&precision=s&u=<账号名称>&p=<密码>"--data-binary 'temperature,location=1 value=90 1472666050'
虽然性能会提高,但是代价是精度越粗糙,越有可能出现具有相同时间戳的重复数据点,可能会覆盖其它数据点。
命令行界面(Influx CLI)
如何使TSDB For InfluxDB®的Influx CLI返回用户可读的时间戳?
在您首次连接Influx CLI时,请指定rfc3339精度:
$ influx -ssl -username <账号名称>-password <密码>-host <网络地址>-port 3242-precision rfc3339
或者,在连接Influx CLI后指定精度:
$ influx -ssl -username <账号名称>-password <密码>-host <网络地址>-port 3242
Connected to https://<网络地址>:3242 version 1.7.x
> precision rfc3339
详情请参见命令行界面。
非admin用户如何使用USE
指定一个数据库?
如果非admin用户拥有数据库的READ
和WRITE
,或仅有READ
权限,那么可以执行USE <database_name>
语句。如果非admin用户尝试用USE
指定一个他们没有READ
和WRITE
,或没有READ
权限的数据库,那么系统会返回错误:
ERR:Database<database_name> doesn't exist. Run SHOW DATABASES for a list of existing databases.
SHOW DATABASES
查询只返回那些非admin用户有READ或WRITE权限的数据库。
如何使用TSDB For InfluxDB®的Influx CLI将数据写入一个非默认的保留策略?
请使用语法INSERT INTO [<database>.]<retention_policy> <line_protocol>
将数据写入一个非默认的保留策略。(只允许在Influx 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来查询非默认保留策略中的数据。使用以下语法完全限定measurement:
"<database>"."<retention_policy>"."<measurement>"
数据类型
为什么不能查询布尔类型的field value?
写入和查询布尔值的语法不一样。
布尔值语法 | 写入 | 查询 |
| √ | ❌ |
| √ | ❌ |
| √ | √ |
| √ | √ |
| √ | √ |
例如:SELECT * FROM "hamlet" WHERE "bool"=True
返回所有bool
等于TRUE
的数据点,但是,SELECT * FROM "hamlet" WHERE "bool"=T
不会返回任何结果。
TSDB For InfluxDB®如何处理多个Shard之间的field的类型差异?
field value可以是浮点数、整数、字符串或者布尔值。在一个Shard中,field value的数据类型需要保持统一,但是在不同的Shard,field value的数据类型可以不同。
SELECT语句
SELECT
语句返回默认所有相同数据类型的field value,如果在不同的Shard里面field value的数据类型不一样,那么TSDB For InfluxDB®首先会执行类型转换(如果适用的话),然后返回所有值,并且按以下数据类型的顺序返回结果:浮点数,整数,字符串,布尔值。如果在您的数据中,field value的类型不同,请使用语法<field_key>::<type>
查询不同的数据类型。示例如下:measurement
just_my_type
有一个名为my_field
的field,my_field
在四个不同的Shard中有四个field value,并且每个field value的数据类型不一样(分别是浮点数、整数、字符串和布尔值)。SELECT
只返回浮点型和整型的field value。在返回结果中TSDB For InfluxDB®强制将整数转换成浮点数。> SELECT * FROM just_my_type name: just_my_type ------------------ time my_field 2016-06-03T15:45:00Z9.87034 2016-06-03T16:45:00Z7
SELECT <field_key>::<type> [...]
返回所有数据类型。TSDB For InfluxDB®将每种类型的数据输出到单独的列中,并且使用递增的列名表示。在可能的情况下,TSDB For InfluxDB®将field value转换成另一种数据类型;它将整数7
转换成第一列中的浮点数,将浮点数9.879034
转换成第二列中的整数。TSDB For 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:00Z9.870349 2016-06-03T16:45:00Z77 2016-06-03T17:45:00Z a string 2016-06-03T18:45:00Z true
SHOW FIELD KEYS查询
SHOW FIELD KEYS
返回field key对应的每个shard中的每种数据类型。示例如下:measurement
just_my_type
有一个名为my_field
的field,my_field
在四个不同的shard中有四个field value,并且每个field value的数据类型不一样(分别是浮点数、整数、字符串和布尔值)。SHOW FIELD KEYS
返回所有四种数据类型:> SHOW FIELD KEYS name: just_my_type fieldKey fieldType ----------------- my_field float my_field string my_field integer my_field boolean
TSDB For InfluxDB®可以存储的最小和最大整数是多少?
TSDB For InfluxDB®将所有整数存储为有符号的int64数据类型。int64有效的最小和最大值分别是-9023372036854775808
和9023372036854775807
。请查看Go builtins获得更多相关信息。
使用接近最小/最大整数但依旧在限制范围内的值可能会导致非预期的结果;有些函数和运算符会在计算过程中将数据类型int64转换成float64,这会引起溢出问题。
TSDB For InfluxDB®可以存储的最小和最大时间戳是多少?
最小的时间戳是-9223372036854775806
或1677-09-21T00:12:43.145224194Z
,最大的时间戳是9223372036854775806
或2262-04-11T23:47:16.854775806Z
。超出该范围的时间戳会返回解析错误。
如何知道存储在field中的数据类型?
SHOW FIELD KEYS
查询还返回field的数据类型。
> SHOW FIELD KEYS FROM all_the_types
name: all_the_types
-------------------
fieldKey fieldType
blue string
green boolean
orange integer
yellow float
是否可以改变field的数据类型?
目前,在改变field的数据类型上面,TSDB For InfluxDB®提供非常有限的支持。语法<field_key>::<type>
支持将field value从整数转换为浮点数或者从浮点数转换为整数。请查看文档数据探索获得更多关于转换操作的信息。无法将浮点数或整数转换为字符串或布尔值(反之亦然)。
我们列出了可用于更改field数据类型的方法:
将数据写入一个不同的field
最简单的解决方法就是将具有新数据类型的数据写入到同一个序列中的不同field。
使用shard系统
在一个shard里面,field value的数据类型不能不一样,但是在不同的shard,field value的数据类型可以不同。
如果要更改field的数据类型,用户可以使用
SHOW SHARDS
查询来识别当前shard的end_time
。如果数据点的时间戳发生在end_time
之后,那么TSDB For InfluxDB®允许将不同数据类型的数据写入到一个现有的field中(例如,field原来接受整数,但是在end_time
之后,该field可以接受浮点数)。请注意,这不会改变原来shard里面field的数据类型。
InfluxQL函数
如何执行函数中的数学运算?
目前,TSDB For InfluxDB®不支持函数内的数学运算。我们建议使用子查询作为解决方法。示例如下:
InfluxQL不支持以下语法:
SELECT MEAN("dogs"-"cats")from"pet_daycare"
相反,我们可以使用子查询获得相同的结果:
> SELECT MEAN("difference") FROM (SELECT "dogs"-"cat" AS "difference" FROM "pet_daycare")
请查看数据探索获得更多关于子查询的信息。
为什么查询将epoch 0作为时间戳返回?
在TSDB For InfluxDB®中,epoch 0(1970-01-01T00:00:00Z
)通常用作空时间戳(null timestamp),如果您请求的查询中没有时间戳返回,例如,对于没有规定时间范围的聚合函数,TSDB For InfluxDB®返回epoch 0作为时间戳。
哪些InfluxQL函数支持嵌套使用?
以下InfluxQL函数支持嵌套使用:
COUNT()
嵌套DISTINCT()
CUMULATIVE_SUM()
DERIVATIVE()
DIFFERENCE()
ELAPSED()
MOVING_AVERAGE()
NON_NEGATIVE_DERIVATIVE()
HOLT_WINTERS()
和HOLT_WINTERS_WITH_FIT()
关于如何使用子查询代替嵌套函数,请查看文档数据探索。