一、数据模型

1、物理量(Measurement,也称工况、字段 field)

物理量,是在实际场景中检测装置所记录的测量信息,且可以按一定规律变换成为电信号或其他所需形式的信息输出并发送给 IoTDB。在 IoTDB 当中,存储的所有数据及路径,都是以物理量为单位进行组织。

2、实体(Entity,也称设备,device)

一个物理实体,是在实际场景中拥有物理量的设备或装置。在 IoTDB 当中,所有的物理量都有其对应的归属实体。

3、存储组(Storage group)

一组物理实体,用户可以将任意前缀路径设置成存储组。

4、数据点(Data point)

一个“时间-值”对

5、时间序列(一个实体的某个物理量对应一个时间序列,Timeseries,也称测点 meter、时间线 timeline,实时数据库中常被称作标签 tag、参数 parameter)

一个物理实体的某个物理量在时间轴上的记录,是数据点的序列。

6、对齐的时间序列(Aligned timeseries)

在实际应用中,存在某些实体的多个物理量同时采样(如 GPS 的经度和维度),形成在时间列上对齐的多条时间序列。

对齐时间序列的时间戳列在内存和磁盘中仅需存储一次,可以减少存储资源的占用。

对齐的多个时间序列需要同时创建,使用关键字 aligned 显式声明

不可以在对齐序列所属的设备下创建非对齐的序列,不可以在非对齐序列所属的设备下创建对齐序列。

查询数据时,可以对于每一条时间序列单独查询。

插入数据时,对齐的时间序列中某列的某些行允许有空值。

7、物理量模板(Schema template)

实际应用中有许多实体所采集的物理量相同,即具有相同的工况名称和类型,可以声明一个物理量模板来定义可采集的物理量集合。在实践中,物理量模板的使用可帮助减少元数据的资源占用。

应用场景与 SQL 设计

场景1:一个物理实体具有多个非对齐的时间序列

// 创建时间序列
// 1. 完整语法(v0.12及之前)
create timeseries root.sg1.d1.s1 with datatype=FLOAT, encoding=RLE, compression=SNAPPY, tags(tag1=v1, tag2=v2), attributes(attr1=v1, attr2=v2)
create timeseries root.sg1.d1.s2 with datatype=FLOAT, encoding=RLE, compression=SNAPPY, tags(tag1=v1, tag2=v2), attributes(attr1=v1, attr2=v2)

// 2. 简化语法(v0.13开始支持,与之前语法兼容)
create timeseries root.sg1.d1.s1 FLOAT encoding=RLE compression=SNAPPY tags(tag1=v1, tag2=v2) attributes(attr1=v1, attr2=v2)
create timeseries root.sg1.d1.s2 FLOAT encoding=RLE compression=SNAPPY tags(tag1=v1, tag2=v2) attributes(attr1=v1, attr2=v2)

// 插入语句
insert into root.sg1.d1(time, s1) values(1,1)
insert into root.sg1.d1(time, s1, s2) values(1,1,2)

场景2:一个物理实体具有一组对齐的时间序列

// 在实体 root.sg1.d2 下创建一组对齐的时间序列
create aligned timeseries root.sg1.d2(s1 FLOAT encoding=RLE, s2 INT32 encoding=Grollia compression=SNAPPY)

// 注:可以指定每条时间序列的编码(encoding)和压缩方式(compression),但是暂不支持指定 props, attributes, tags 等。

// 插入语句,必须使用 aligned 关键词
insert into root.sg.d2(time, s1, s2) aligned values(1, 1, 2)
insert into root.sg.d2(time, s1) aligned values(2, 1)  //允许单独写某条时间序列,其他时间序列在该时间点上为空值

// 场景2所创建的对齐时间序列所属物理实体可以扩充时间序列,但需要在该物理实体下嵌套新实体。
// 例如,可以向d2下继续添加时间序列: 
create timeseries root.sg1.d2.t1.s1 FLOAT
create timeseries root.sg1.d2.v1.(s1 FLOAT, s2 FLOAT)

场景3:一个物理实体具有多组对齐的时间序列

// 创建语句
create aligned timeseries root.sg1.d3.v1(s1 FLOAT, s2 INT32)
create aligned timeseries root.sg1.d3.v2(s1 FLOAT, s2 INT32)
 
// 插入语句,不能同时向多组对齐的时间序列中插入值
insert into root.sg1.d3.v1(time, s1, s2) aligned values(1, 1, 2)
insert into root.sg1.d3.v1(time, s1) aligned values(2, 3)
insert into root.sg1.d3.v2(time, s1, s2) aligned values(1, 1, 2)
insert into root.sg1.d3.v2(time, s2) aligned values(3, 4)

场景4:一个物理实体具有混合的非对齐和对齐的时间序列

// 创建语句
create timeseries root.sg1.d4.t1.s1 FLOAT
create aligned timeseries root.sg1.d4.v1(s1 FLOAT, s2 INT32)
create aligned timeseries root.sg1.d4.v2(s1 FLOAT, s2 INT32)

// 插入语句,不能同时向非对齐和对齐的时间序列中插入值
insert into root.sg1.d4.t1(time, s1) values(1, 1)
insert into root.sg1.d4.v1(time, s1, s2) aligned values(1, 1, 2)
insert into root.sg1.d4.v1(time, s1) aligned values(2, 3)
insert into root.sg1.d4.v2(time, s1, s2) aligned values(1, 1, 2)
insert into root.sg1.d4.v2(time, s2) aligned values(3, 4)

三、Session API

注意:以下仅展示本次新增的 session API,其他 API 与旧有 API 相同的不在此展示,如:查询语句(executeRawDataQuery)。

1、创建一组对齐的时间序列

void createAlignedTimeseries(
	String prefixPath, // "root.sg.d1.陀螺仪" 
	List<String> measurements,
	List<TSDataType> dataTypes,
	List<TSEncoding> encodings, 
	CompressionType compressor, 
	List<String> measurementAliasList
);

2、插入Record

一个 Record 是一个设备一个时间戳下多个测点的数据,例如:

insert into root.sg1.d1.v1(time, s1, s2) aligned values(1,1,2)

API 如下:

// 服务器需要做类型推断,可能会有额外耗时
void insertAlignedRecord(String prefixPath, long time, List<String> measurements, List<String> values)

// 提供数据类型后,服务器不需要做类型推断,可以提高性能
void insertAlignedRecord(String prefixPath, long time, List<String> measurements, List<TSDataType> types, List<Object> values)

// 应用到上面的例子即:
void insertAlignedRecord(
    "root.sg1.d1.v1",
    1,
    Arrays.asList("s1", "s2"),
    Arrays.asList("1", "2")
)

// 只插入到部分序列,其他序列值自动置为 null
void insertAlignedRecord(
    "root.sg1.d1.v1",
    1,
    Arrays.asList("s1"),
    Arrays.asList("1")
)

// 也可以通过null显式声明
void insertAlignedRecord(
    "root.sg1.d1.v1",
    1,
    Arrays.asList("s1","s2"),
    Arrays.asList("1",null)
)

3、插入Tablet

Tablet 是一个设备若干行非空数据块,每一行的列都相同

// 插入一个 Tablet
void insertTablet(Tablet tablet) 

// 插入多个 Tablet
void insertTablets(Map<String, Tablet> tablet)

// 对齐的时间序列通过 measurementSchema 构建 Tablet
List<IMeasurementSchema> schemaList = new ArrayList<>();
schemaList.add(new measurementSchema(new String[] {"s1", "s2"}, new TSDataType[] {TSDataType.INT64, TSDataType.INT32}));
Tablet tablet = new Tablet("root.sg1.d1.v1", schemaList);
  • No labels

2 Comments

  1. We have some new ideas on data concept and SQL design of aligned timeseries. The details are as follows:

    Vector SQL 设计 & 对数据模型的重新思考