InfluxDb中的schema设计

处理不同的事情的时候,每个人设计InfluxDB可能都是不一样的,每个人有不同的经验,他们会根据自己的经验设计自己的数据库。

前人总结了很多设计时序数据库的经验,这里分享给大家,从而让大家少走弯路,避免陷阱,这样就有更多时间去陪家人了。

本文可以算最佳实践了,如果你至今还没操作过InfluxDb,兄弟,那么这篇文章你读起来,可以没有感觉。


哪些情况下使用tag

在设计时序库时,哪些属性使用tag,哪些属性使用field,可能会使我们迷惑很久。我们这里再强调一次,tag和field的区别是,tag会自动加上索引,而field不会,tag value只能存储字符串,field可以存储任何类型。

按照这个思路,一般来说,你的查询可以指引你哪些数据放在tag中,哪些放在field中。只要查询中有的属性,建议你放到tag中:

  • 把你经常查询的字段作为tag
  • 如果你要对其使用GROUP BY(),也要放在tag中
  • 如果你要对其使用InfluxQL函数,则将其放到field中,因为tag只能是字符串。大多数函数,如求和,对字符串是没有用的。是不是很好理解呢?
  • 如果你需要存储的值不是字符串,则需要放到field中,因为tag value只能是字符串

避免InfluxQL中关键字作为标识符名称

避免InfluxQL中关键字作为标识符名称,这不是必需的,但它简化了写查询,您不必将这些标识符包装在双引号中。其实mysql也有类似这样的最佳实践。

标识符有database名称,retention policy名称,user名,measurement名称,tag key和field key。请参阅InfluxQL关键词看下哪些单词需要被避免。

请注意,如果查询中包含除[A-z,_]以外的字符,则还需要将它们用双引号括起来。


不要有太多的序列series

tags包含高度可变的信息,如UUID,哈希值和随机字符串,这将导致数据库中的大量measurement,通俗地说是高序列数(series cardinality)。序列数高会使内存使用急剧增加,所以设计时候要小心。

请参阅硬件指南中基于你的硬件的series cardinality的建议。如果系统有内存限制,请考虑将高cardinality数据存储为field而不是tag。


如何设计InfluxDb表measurement

一般来说,谈论这一步可以简化你的查询。InfluxDB的查询会合并属于同一measurement范围内的数据; 用tag区分数据比使用详细的measurement名字更好。

例如:考虑如下的schema:

Schema 1 - Data encoded in the measurement name
-------------
blueberries.plot-1.north temp=50.1 1472515200000000000
blueberries.plot-2.midwest temp=49.8 1472515200000000000

blueberries.plot-1.north是measurement的名字,这个表是没有tag的哦,像plotnorth这样的信息放在measurement名字里面将会使数据很难去查询。

上面temp是温度的意思,有些同学会疑问,地球上哪个地方的温度会超过50度。生物在50度能活下来吗?哈哈,这里的温度是华氏度,华氏度50度,只相对于摄氏度的10度而已。

例如,使用上面的模式(schema 1)计算两个plot1和plot2的平均temp很困难,需要使用到效率低的正则表达式。如下:

# Schema 1 - Query for data encoded in the measurement name
> SELECT mean("temp") FROM /\.north$/

我们队模式(schema 1)进行改造一下,变为模式2:

Schema 2 - Data encoded in 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

以下查询计算了落在北部地区的蓝莓的平均temp,这种查询是不是很简单。但是,需要注意,它也有弱点,就是没有使用索引tag,使用的是field,大数量的情况下,效率并不高。

# Schema 2 - Query for data encoded in tags
> SELECT mean("temp") FROM "weather_sensor" WHERE "region" = 'north'

不要把多条信息放到一个tag里面

与上述相似,将多个属性编入一个tag并不好,至少从查询上很不方面。

例如,考虑如下的schema:

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

上述数据将多个单独的参数plot``region放到了一个长tag value里面(plot-1.north)。 这时候查询只能用基于正则的模糊查询,下面的查询表示location中包含north的被查出。

# Schema 1 - Query for multiple data encoded in a single tag
> SELECT mean("temp") FROM "weather_sensor" WHERE location =~ /\.north$/

我们来分解一下,得到模式2:

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

以下查询计算了落在north地区的蓝莓的平均temp。 虽然这两个查询都是相似的,但在Schema 2中使用多个tag避免了使用正则表达式。

# Schema 2 - Query for data encoded in multiple tags
> SELECT mean("temp") FROM "weather_sensor" WHERE region = 'north'

shard group的保留时间(duration)的管理


shard group的保留时间(duration)预览

InfluxDB将数据存储在shard group中。shard group由存储策略(RP)管理,并存储具有特定时间间隔内的时间戳的数据。 该时间间隔的长度称为shard group的duration。

默认情况下,shard group的duration是由RP的duration决定:

RP duration shard group duration
< 2 days a hour
>= 2 days and <= 6 months 1 day
> 6 months 7 days

在每个RP上shard group的duration也是可以配置的,可以看Retention Policy管理看如何配置shard group的duration。


shard group的duration的建议

通常,较短的shard group的duration允许系统有效地丢弃数据。 当InfluxDB强制执行RP时,它会丢弃整个shard group,而不是单个数据点。 例如,如果您的RP有一天的持续时间,一个shard group持续时间为一小时; 则InfluxDB每小时将丢弃一小时的数据。

如果您的RP的持续时间大于6个月,则不需要具有较短的shard group持续时间。 事实上,将shard group的持续时间提高到默认的七天值以上可以改善压缩,提高写入速度,并减少每个shard group的固定迭代器开销。 例如,50年及以上的shard group持续时间是可接受的配置。

说明:当配置shard group的duration的时候,INF(infinite)是一个不合理的配置。在实际工作中,特定的duration1000w就足够达到非常长的shard group持续时间。

我们建议shard group的配置如下:

  • 是你一般查询时间范围的两倍
  • 每个shard group里至少有100000个数据点
  • 每个shard group里面的每个series至少有1000个数据点