全部产品
云市场

时序数据模型设计方法

更新时间:2020-01-02 21:40:43

时序数据模型简介

时序数据(Time Series Data)是基于相对稳定频率持续产生的一系列指标监测数据。例如,监测某城市的空气质量时,每秒采集一个二氧化硫浓度的值而产生的一系列数据。在时序数据模型中,通常有以下这些通用概念:

  • 度量(Metric):监测数据的指标,例如风力和温度。
  • 标签(Tag): 度量(Metric)虽然指明了要监测的指标项,但没有指明要针对什么对象的该指标项进行监测。标签(Tag)就是用于表明指标项监测针对的具体对象,属于指定度量下的数据子类别。

    一个标签(Tag)由一个标签键(TagKey)和一个对应的标签值(TagValue)组成,例如“城市(TagKey)= 杭州(TagValue)”就是一个标签(Tag)。更多标签示例:机房 = A 、IP = 172.220.110.1。

    注意:当标签键和标签值都相同才算同一个标签;标签键相同,标签值不同,则是不同的标签。

    在监测数据的时候,指定度量是“气温”,标签是“城市 = 杭州”,则监测的就是杭州市的气温。

    • 标签键(TagKey,Tagk):为指标项(Metric)监测指定的对象类型(会有对应的标签值来定位该对象类型下的具体对象),例如国家、省份、城市、机房、IP 等。

    • 标签值(TagValue,Tagv):标签键(TagKey)对应的值。例如,当标签键(TagKey)是“国家”时,可指定标签值(TagValue)为“中国”。

  • 值(Value):度量对应的值,例如 15 级(风力)和 20 ℃(温度)。在时序模型中,通常在一个度量下面存在一个值或者多个更加细分的值: 比如一个为温度(temperature)的度量,可能只有单纯的一个值,也有可能细分为 室内温度(indoor)和室外温度(outdoor)。这便是时序数据模型中称为“单值模型”和“多值模型”的区别。具体要设计为单值模型还是多值模型,则取决于业务需求。

  • 时间戳(Timestamp):数据(度量值)产生的时间点。

  • 时间序列(Time Series):针对某个监测对象的某项指标(由度量和标签定义)的描述。“一个度量 + N 个标签KV组合(N >= 1)”定义为一个时间序列,某个时间序列上产生的数据值的增加,不会导致时间序列的增加。 时间序列的示意图如下: 时间序列示意图

时序数据模型的表设计

在TSDB 2.0中,数据是按照类似关系型数据库中的数据表(Table)进行组织与存储的。因此在TSDB 2.0中实际写入数据之前,需要预先设计并创建好表。下文将介绍在TSDB 2.0中,如何基于上述的时序数据模型设计时序数据的数据表。

  • 度量(Metric):将度量名定义为表名是一个不错的选择
  • 标签(Tag):由于标签自身通常是一些字符串,因此建议将标签按标签名定义为列名,并且将标签列定义为字符串类型(TEXT)。这样,TSDB 2.0将会自动对标签列建立倒排索引,从而使基于标签的查询更加高效

    在另外一些场景下,可能时序数据模型未来还会加入一些新的标签,但是这些标签在设计数据表时尚未拥有明确定义。因此可以考虑预留动态类型(OBJECT)的列作为今后标签的扩展,以免在未来加了新了标签时重新建表 或 执行 表变更操作。

    关于动态类型OBJECT,可以详细参考 数据类型 章节

  • 值(Value):建议将度量的值定义为列。如果是单值模型,则可设计为单独的一列;如果是多值模型,则可根据值种类的个数定义不同的列用于存储不同种类的值。列的类型则根据时序数据的实际情况定义为任意类型。大多数情况下可以考虑使用INTEGERDOUBLE PRECISION类型。

  • 时间戳(Timestamp):建议将时间戳定义为一个 TIMESTAMP WITH TIMEZONETIMESTAMP WITHOUT TIMEZONE的列

这样一来,一个标准的时序数据模型就被设计成了TSDB 2.0中的一个数据表。以上一小节中的 时间序列示意图 所示的模型为例,依据上述设计建议设计出的数据表如下所示:

时序模型数据表

此外,对于一些时序模型与空间数据混合的业务场景,建议可以直接将数值列的类型定义为 空间类型。这样,便可以充分发挥TSDB 2.0的时序时空数据的查询分析能力。

表设计中的数据分片策略

由于时序数据运用的场景下,数据量往往都非常巨大。对于一个传统的关系型数据库而言,如果数据只是存在一张单表中,随着生产环境中积攒的时序数据量的增大,无论对于其查询性能还是写入性能都会有明显的性能损耗。

所幸 TSDB 2.0是一个分布式数据库并天然提供了数据分片以及并行查询的能力。因此我们在设计时可以按照上文所示将同一度量的时序数据都保存在一张数据表中,如果预见数据量会不断增大,那么建议在建表时随着建表DDL语句指定好数据分片策略,即可充分发挥TSDB 2.0 的数据分片以及并行查询的能力。

关于 TSDB 2.0的 数据分片特性,在 分片 一文中给了详细的说明,此处不再展开。这里将结合上述 温度数据的例子,介绍时序数据建表时推荐的 分片策略:

  1. 将数据按时间分区.

    通常,时序数据在时间维度上将会产生大量的时间戳。为了方便基于时间维度的查询分析,推荐在时间维度进行分区。方法是

    1. 设计时间分区的单位,基于 GENERATED ALWAYS 语句建立用于进行时间分区的自动生成列.
    2. 通过PARTITIONED BY语句指定数据按照上述的自动生成列进行分区

      注意:在设计时间分区的单位时,不建议将单位设计过小。因为分区单位过小会导致单个分区规模太小且分区数过多。当分区数太多时将可能元数据管理成为瓶颈,引起严重的性能问题和稳定性问题。建议对于时间维度分区时以 “天”,“周”或更上的粒度为单位。

  2. 将数据基于特定标签分片

    对于时序数据的标签而言,有些标签是用于进行数据分类的标签。无乱时间序列最终会有多少个,这类标签的可能值的范围是相对有限的。那么建议在时间分区的基础上进一步按照此类标签值进行数据分片。从而将数据进一步打散至 TSDB 2.0实例集群中的不同节点上。方法是

    1. 通过CLUSTERED BY语句指定数据分片所依据的标签列的列名

      注意:不建议将能够唯一区分时间序列的标签作为 CLUSTERED BY 中指定的列名。原因是通常一个TSDB 2.0的集群中节点数是相对有限的,如果将唯一性标签作为分片key,有可能会导致大量不同的标签值被分片到同一节点,这将会使分片的意义减弱

以第一节中的 temperature 的度量数据模型为例。结合上述数据分片的最佳实践,最终我们可以在TSDB 2.0中建表时采用下述建表语句

  1. CREATE TABLE temperature (
  2. ts TIMESTAMP WITH TIME ZONE,
  3. floor TEXT,
  4. room TEXT,
  5. device_id TEXT,
  6. value DOUBLE PRECISION,
  7. day TIMESTAMP WITH TIME ZONE GENERATED ALWAYS AS date_trunc('day', ts))
  8. CLUSTERED BY (floor) PARTITIONED BY (day);

关于建表语句中所使用的GENERATED ALWAYS以及CLUSTERED BY,详细请参见 SQL语法 章节