| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| --> |
| # 树转表视图 |
| |
| ## 1. 功能概述 |
| |
| IoTDB 提供了树转表功能,支持通过创建表视图的方式,将已存在的树模型数据转化为表视图,进而通过表视图进行查询,实现了对同一份数据的树模型和表模型协同处理: |
| |
| * 数据写入阶段,采用树模型语法,支持数据灵活接入和扩展。 |
| * 数据分析阶段,采用表模型语法,支持通过标准 SQL 查询语言,执行复杂的数据分析。 |
| |
|  |
| |
| > - V2.0.5 及以后版本支持该功能。 |
| > - 表视图只读,不允许通过表视图写入数据。 |
| |
| ## 2. 功能介绍 |
| ### 2.1 创建表视图 |
| #### 2.1.1 语法定义 |
| |
| ```SQL |
| -- create (or replace) view on tree |
| CREATE |
| [OR REPLACE] |
| VIEW view_name ([viewColumnDefinition (',' viewColumnDefinition)*]) |
| [comment] |
| [RESTRICT] |
| [WITH properties] |
| AS prefixPath |
| |
| viewColumnDefinition |
| : column_name [dataType] TAG [comment] # tagColumn |
| | column_name [dataType] TIME [comment] # timeColumn |
| | column_name [dataType] FIELD [FROM original_measurement] [comment] # fieldColumn |
| ; |
| |
| comment |
| : COMMENT string |
| ; |
| ``` |
| |
| > 注意:列仅支持 tag / field / time,不支持 attribute。 |
| |
| #### 2.1.2 语法说明 |
| 1. **`prefixPath`** |
| |
| 对应树模型的路径,路径最后一级必须为 `**`,且其他层级均不能出现 `*` 或 `**`。该路径确定 VIEW 对应的子树。 |
| |
| 2. **`view_name`** |
| |
| 视图名称,与表名相同(具体约束可参考[创建表](../Basic-Concept/Table-Management_apache.md#\_1-1-创建表)),如 db.view。 |
| |
| 3. **`viewColumnDefinition`** |
| |
| * `TAG`:每个 Tag 列按顺序对应`prefixPath`后面层级的路径节点。 |
| * `FIELD`:FIELD 列对应树模型中的测点(叶子节点)。 |
| * 若指定了 FIELD 列,则列名使用声明中的`column_name`。 |
| * 若声明了 `original_measurement`,则直接映射到树模型该测点。否则取小写`column_name` 作为测点名进行树模型映射。 |
| * 不支持多个 FIELD 映射到树模型同名测点。 |
| * 若未指定 FIELD 列的 `dataType`,则默认获取树模型映射测点的数据类型。 |
| * 若树模型中的设备不包含某些声明的 FIELD 列,或与声明的 FIELD 列的数据类型不一致,则在查询该设备时,该 FIELD 列的值永远为 NULL。 |
| * 若未指定 FIELD 列,则创建时会自动扫描出`prefixPath`子树下所有的测点(包括定义为所有普通序列的测点,以及挂载路径与 `prefixPath `有所重合的所有模板中的测点),列名使用树模型测点名称。 |
| * 不支持树模型存在名称(含小写)相同但类型不同的测点 |
| * `TIME`:创建视图时可以不指定时间列(TIME),IoTDB 会自动添加该列并命名为"time", 且顺序上位于第一列。自 V2.0.8 版本起,支持创建视图时**自定义命名时间列**,自定义时间列在视图中的顺序由创建 SQL 中的顺序决定。相关约束如下: |
| * 当列分类(columnCategory)设为 `TIME` 时,数据类型(dataType)必须为 `TIMESTAMP`。 |
| * 每个视图最多允许定义 1个时间列(columnCategory = TIME)。 |
| * 当未显式定义时间列时,不允许其他列使用 `time` 作为名称,否则会与系统默认时间列命名冲突。 |
| |
| 4. **`WITH properties`** |
| |
| 目前仅支持 TTL,表示该视图 TTL ms 之前的数据不会在查询时展示,即`WHERE time > now() - TTL`。若树模型设置了 TTL,则查询时取两者中的更小值。 |
| |
| > 注意:表视图 TTL 不影响树模型中设备的真实 TTL,当设备数据达到树模型设定的 TTL 后,将被系统物理删除。 |
| |
| 5. **`OR REPLACE`** |
| |
| table 与 view 不能重名。创建时若已存在同名 table ,则会报错;若已存在同名 view ,则进行替换。 |
| |
| 6. **`RESTRICT`** |
| |
| 约束匹配树模型设备的层级数(从 prefixPath 下一层开始),若有 RESTRICT 字段,则匹配层级完全等于 tag 数量的 device,否则匹配层级小于等于 tag 数量的 device。默认非 RESTRICT,即匹配层级小于等于 tag 数量的 device。 |
| |
| #### 2.1.3 使用示例 |
| 1. 树模型及表视图原型 |
| |
|  |
| |
| 2. 创建表视图 |
| |
| * 创建语句 |
| |
| ```SQL |
| CREATE OR REPLACE VIEW viewdb."风机表" |
| ("风机组" TAG, |
| "风机号" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| with (ttl=604800000) |
| AS root.db.** |
| ``` |
| |
| * 具体说明 |
| |
| 该语句表示,创建出名为 `viewdb."风机表"` 的视图(viewdb 如不存在会报错),如果该视图已存在,则替换该视图: |
| |
| * 为挂载于树模型 root.db.\*\* 路径下面的序列创建表视图。 |
| * 具备`风机组`、`风机号`两个 `TAG` 列,因此表视图中只包含原树模型中第 3 层上的设备。 |
| * 具备`电压`、`电流`两个 `FIELD` 列。这里两个 `FIELD` 列对应树模型下的序列名同样是`电压`、`电流`,且仅仅选取类型为 `DOUBLE` 的序列。 |
| |
| **序列名的改名需求:**如果树模型下的序列名为`current`,想要创建出的表视图中对应的 `FIELD` 列名为`电流`,这种情况下,SQL 变更如下: |
| |
| ```SQL |
| CREATE OR REPLACE VIEW viewdb."风机表" |
| ("风机组" TAG, |
| "风机号" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD FROM current |
| ) |
| AS root.db.** |
| with (ttl=604800000) |
| ``` |
| |
| * 当需要自定义时间列(V2.0.8 起支持)时,SQL 变更如下: |
| |
| ```SQL |
| CREATE OR REPLACE VIEW viewdb."风机表" |
| ("风机组" TAG, |
| "风机号" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD, |
| time_user_defined TIMESTAMP TIME |
| ) |
| AS root.db.** |
| with (ttl=604800000) |
| ``` |
| |
| ### 2.2 修改表视图 |
| #### 2.2.1 语法定义 |
| |
| 修改表视图功能支持修改视图名称、添加列、列重命名、删除列、设置视图的 TTL 属性,以及通过 COMMENT 添加注释。 |
| |
| ```SQL |
| -- 修改视图名 |
| ALTER VIEW [IF EXISTS] viewName RENAME TO to=identifier |
| |
| -- 在视图中添加某一列 |
| ALTER VIEW [IF EXISTS] viewName ADD COLUMN [IF NOT EXISTS] viewColumnDefinition |
| viewColumnDefinition |
| : column_name [dataType] TAG # tagColumn |
| | column_name [dataType] FIELD [FROM original_measurement] # fieldColumn |
| |
| -- 为视图中的某一列重命名 |
| ALTER VIEW [IF EXISTS] viewName RENAME COLUMN [IF EXISTS] oldName TO newName |
| |
| -- 删除视图中的某一列 |
| ALTER VIEW [IF EXISTS] viewName DROP COLUMN [IF EXISTS] columnName |
| |
| -- 修改视图的 TTL |
| ALTER VIEW [IF EXISTS] viewName SET PROPERTIES propertyAssignments |
| |
| -- 添加注释 |
| COMMENT ON VIEW qualifiedName IS (string | NULL) #commentView |
| COMMENT ON COLUMN qualifiedName '.' column=identifier IS (string | NULL) #commentColumn |
| ``` |
| |
| #### 2.2.2 语法说明 |
| 1. `SET PROPERTIES`操作目前仅支持对表视图的 TTL 属性进行配置。 |
| 2. 删除列功能,仅支持删除物理量列(FIELD),标识列(TAG)不支持删除。 |
| 3. 修改后的 comment 会覆盖原有注释,如果指定为 null,则会擦除之前的 comment。 |
| #### 2.2.3 使用示例 |
| |
| ```SQL |
| -- 修改视图名 |
| ALTER VIEW IF EXISTS tableview1 RENAME TO tableview |
| |
| -- 在视图中添加某一列 |
| ALTER VIEW IF EXISTS tableview ADD COLUMN IF NOT EXISTS temperature float field |
| |
| -- 为视图中的某一列重命名 |
| ALTER VIEW IF EXISTS tableview RENAME COLUMN IF EXISTS temperature TO temp |
| |
| -- 删除视图中的某一列 |
| ALTER VIEW IF EXISTS tableview DROP COLUMN IF EXISTS temp |
| |
| -- 修改视图的 TTL |
| ALTER VIEW IF EXISTS tableview SET PROPERTIES TTL=3600 |
| |
| -- 添加注释 |
| COMMENT ON VIEW tableview IS '树转表' |
| COMMENT ON COLUMN tableview.status is Null |
| ``` |
| |
| ### 2.3 删除表视图 |
| #### 2.3.1 语法定义 |
| |
| ```SQL |
| DROP VIEW [IF EXISTS] viewName |
| ``` |
| |
| #### 2.3.2 使用示例 |
| |
| ```SQL |
| DROP VIEW IF EXISTS tableview |
| ``` |
| |
| ### 2.4 查看表视图 |
| #### 2.4.1 **`Show Tables`** |
| 1. 语法定义 |
| |
| ```SQL |
| SHOW TABLES (DETAILS)? ((FROM | IN) database_name)? |
| ``` |
| |
| 2. 语法说明 |
| |
| `SHOW TABLES (DETAILS)` 语句通过结果集的`TABLE_TYPE`字段展示表或视图的类型信息: |
| |
| | 类型 | `TABLE_TYPE`字段值 | |
| | -------------------------------------- | ------------------------ | |
| | 普通表(Table) | `BASE TABLE` | |
| | 树转表视图(Tree View) | `VIEW FROM TREE` | |
| | 系统表(Iinformation\_schema.Tables) | `SYSTEM VIEW` | |
| |
| 3. 使用示例 |
| |
| ```SQL |
| IoTDB> show tables details from database1 |
| +-----------+-----------+------+-------+--------------+ |
| | TableName| TTL(ms)|Status|Comment| TableType| |
| +-----------+-----------+------+-------+--------------+ |
| | tableview| INF| USING| 树转表 |VIEW FROM TREE| |
| | table1|31536000000| USING| null| BASE TABLE| |
| | table2|31536000000| USING| null| BASE TABLE| |
| +-----------+-----------+------+-------+--------------+ |
| |
| IoTDB> show tables details from information_schema |
| +--------------+-------+------+-------+-----------+ |
| | TableName|TTL(ms)|Status|Comment| TableType| |
| +--------------+-------+------+-------+-----------+ |
| | columns| INF| USING| null|SYSTEM VIEW| |
| | config_nodes| INF| USING| null|SYSTEM VIEW| |
| |configurations| INF| USING| null|SYSTEM VIEW| |
| | data_nodes| INF| USING| null|SYSTEM VIEW| |
| | databases| INF| USING| null|SYSTEM VIEW| |
| | functions| INF| USING| null|SYSTEM VIEW| |
| | keywords| INF| USING| null|SYSTEM VIEW| |
| | models| INF| USING| null|SYSTEM VIEW| |
| | nodes| INF| USING| null|SYSTEM VIEW| |
| | pipe_plugins| INF| USING| null|SYSTEM VIEW| |
| | pipes| INF| USING| null|SYSTEM VIEW| |
| | queries| INF| USING| null|SYSTEM VIEW| |
| | regions| INF| USING| null|SYSTEM VIEW| |
| | subscriptions| INF| USING| null|SYSTEM VIEW| |
| | tables| INF| USING| null|SYSTEM VIEW| |
| | topics| INF| USING| null|SYSTEM VIEW| |
| | views| INF| USING| null|SYSTEM VIEW| |
| +--------------+-------+------+-------+-----------+ |
| ``` |
| |
| #### 2.4.2 **`Show Create View`** |
| 1. 语法定义 |
| |
| ```SQL |
| SHOW CREATE VIEW viewname; |
| ``` |
| |
| 2. 语法说明 |
| |
| * 该语句用于获取表视图的完整定义语句。 |
| * 该语句会自动补全创建时省略的所有默认值,因此结果集中所展示的语句可能与原始创建语句不同。 |
| * 该语句不支持用于展示系统表; |
| |
| 3. 使用示例 |
| |
| ```SQL |
| IoTDB> show create view tableview |
| +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
| | View| Create View| |
| +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
| |tableview|CREATE VIEW "tableview" ("device" STRING TAG,"model" STRING TAG,"status" BOOLEAN FIELD,"hardware" STRING FIELD) COMMENT '表视图' WITH (ttl=INF) AS root.ln.**| |
| +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
| ``` |
| |
| > 除此之外,还支持通过 `show create table` 语句查看表视图创建信息,相关详细介绍可查看[show create table](../Basic-Concept/Table-Management_apache.md#_1-4-查看表的创建信息) |
| |
| |
| ### 2.5 非对齐与对齐设备的查询差异 |
| |
| 树转表视图在查询对齐设备和非对齐设备中有 null 值的情况下结果**可能与等价的树模型 align by device 查询不同**。 |
| |
| * **对齐设备** |
| * 树模型的查询表现:当查询涉及的所有序列在某一行都是null时,不保留该行 |
| * 表视图的查询表现:与表模型一致,保留全是 null 的行 |
| * **非对齐设备** |
| * 树模型的查询表现:当查询涉及的所有序列在某一行都是null时,不保留该行 |
| * 表视图的查询表现:与树模型一致,不保留全是 null 的行 |
| * **说明示例** |
| * 对齐 |
| |
| ```SQL |
| -- 树模型写入数据(对齐) |
| CREATE ALIGNED TIMESERIES root.db.battery.b1(voltage INT32, current FLOAT) |
| INSERT INTO root.db.battery.b1(time, voltage, current) aligned values (1, 1, 1) |
| INSERT INTO root.db.battery.b1(time, voltage, current) aligned values (2, null, 1) |
| |
| -- 创建 VIEW 语句 |
| CREATE VIEW view1 (battery_id TAG, voltage INT32 FIELD, current FLOAT FIELD) as root.db.battery.** |
| |
| -- 查询 |
| IoTDB> select voltage from view1 |
| +-------+ |
| |voltage| |
| +-------+ |
| | 1| |
| | null| |
| +-------+ |
| Total line number = 2 |
| ``` |
| |
| * 非对齐 |
| |
| ```SQL |
| -- 树模型写入数据(非对齐) |
| CREATE TIMESERIES root.db.battery.b1.voltage INT32 |
| CREATE TIMESERIES root.db.battery.b1.current FLOAT |
| INSERT INTO root.db.battery.b1(time, voltage, current) values (1, 1, 1) |
| INSERT INTO root.db.battery.b1(time, voltage, current) values (2, null, 1) |
| |
| -- 创建 VIEW 语句 |
| CREATE VIEW view1 (battery_id TAG, voltage INT32 FIELD, current FLOAT FIELD) as root.db.battery.** |
| |
| -- 查询 |
| IoTDB> select voltage from view1 |
| +-------+ |
| |voltage| |
| +-------+ |
| | 1| |
| +-------+ |
| Total line number = 1 |
| |
| -- 如果在查询语句中指定了所有 field 列,或是仅指定了非 field 列时,才可以确保查到所有行 |
| IoTDB> select voltage,current from view1 |
| +-------+-------+ |
| |voltage|current| |
| +-------+-------+ |
| | 1| 1.0| |
| | null| 1.0| |
| +-------+-------+ |
| Total line number = 2 |
| |
| IoTDB> select battery_id from view1 |
| +-------+ |
| |battery_id| |
| +-------+ |
| | b1| |
| | b1| |
| +-------+ |
| Total line number = 2 |
| |
| -- 如果查询中同时有部分 field 列,那最终结果的行数取决于这部分 field 列根据时间戳对齐后的行数 |
| IoTDB> select time,voltage from view1 |
| +-----------------------------+-------+ |
| | time|voltage| |
| +-----------------------------+-------+ |
| |1970-01-01T08:00:00.001+08:00| 1| |
| +-----------------------------+-------+ |
| Total line number = 1 |
| ``` |
| |
| ## 3. 场景示例 |
| ### 3.1 原树模型管理了多种类型的设备 |
| |
| * 场景中不同类型的设备具备不同的层级路径和测点集合。 |
| * **写入时**:在数据库节点下按设备类型创建分支,每种设备下可以有不同的测点结构 |
| * **查询时**:为每种类型的设备建立一张表,每个表具有不同的标签和测点集合 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| -- 风机表 |
| CREATE VIEW viewdb."风机表" |
| ("风机组" TAG, |
| "风机号" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| AS root.db."风机".** |
| |
| -- 电机表 |
| CREATE VIEW viewdb."电机表" |
| ("电机组" TAG, |
| "电机号" TAG, |
| "功率" FLOAT FIELD, |
| "电量" FLOAT FIELD, |
| "温度" FLOAT FIELD |
| ) |
| AS root.db."电机".** |
| ``` |
| |
| ### 3.2 原树模型中没有设备,只有测点 |
| |
| 如场站的监控系统中,每个测点都有唯一编号,但无法对应到某些设备 |
| |
| > 大宽表形式 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| CREATE VIEW viewdb.machine |
| (DCS_PIT_02105A DOUBLE FIELD, |
| DCS_PIT_02105B DOUBLE FIELD, |
| DCS_PIT_02105C DOUBLE FIELD, |
| ... |
| DCS_XI_02716A DOUBLE FIELD |
| ) |
| AS root.db.** |
| ``` |
| |
| ### 3.3 原树模型中一个设备既有子设备,也有测点 |
| |
| 如在储能场景中,每一层结构都要监控其电压和电流 |
| |
| * **写入时**:按照物理世界的监测点,对每一层结构进行建模 |
| * **查询时**:按照设备分类,建立多个表对每一层结构信息进行管理 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| -- 电池舱表 |
| CREATE VIEW viewdb."电池舱表" |
| ("电池站" TAG, |
| "电池舱" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| RESTRICT |
| AS root.db.** |
| |
| -- 电池堆表 |
| CREATE VIEW viewdb."电池堆表" |
| ("电池站" TAG, |
| "电池舱" TAG, |
| "电池堆" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| RESTRICT |
| AS root.db.** |
| |
| -- 电池簇表 |
| CREATE VIEW viewdb."电池簇表" |
| ("电池站" TAG, |
| "电池舱" TAG, |
| "电池堆" TAG, |
| "电池簇" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| RESTRICT |
| AS 'root.db.**' |
| |
| -- 电芯表 |
| CREATE VIEW viewdb."电芯表" |
| ("电池站" TAG, |
| "电池舱" TAG, |
| "电池堆" TAG, |
| "电池簇" TAG, |
| "电芯" TAG, |
| "电压" DOUBLE FIELD, |
| "电流" DOUBLE FIELD |
| ) |
| RESTRICT |
| AS root.db.** |
| ``` |
| |
| ### 3.4 原树模型中一个设备下只有一个测点 |
| |
| > 窄表形式 |
| |
| #### 3.4.1 所有测点数据类型相同 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| CREATE VIEW viewdb.machine |
| ( |
| sensor_id STRING TAG, |
| value DOUBLE FIELD |
| ) |
| AS root.db.** |
| ``` |
| |
| #### 3.4.2 测点的数据类型不相同 |
| ##### 3.4.2.1 为每一种数据类型的测点建一个窄表视图 |
| |
| **优点**:表视图数量是常数个,仅与系统中的数据类型相关 |
| |
| **缺点**:查询某一个测点值时,需要提前知道其数据类型,再去决定查询哪张表视图 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| CREATE VIEW viewdb.machine_float |
| ( |
| sensor_id STRING TAG, |
| value FLOAT FIELD |
| ) |
| AS root.db.** |
| |
| CREATE VIEW viewdb.machine_double |
| ( |
| sensor_id STRING TAG, |
| value DOUBLE FIELD |
| ) |
| AS root.db.** |
| |
| CREATE VIEW viewdb.machine_int32 |
| ( |
| sensor_id STRING TAG, |
| value INT32 FIELD |
| ) |
| AS root.db.** |
| |
| CREATE VIEW viewdb.machine_int64 |
| ( |
| sensor_id STRING TAG, |
| value INT64 FIELD |
| ) |
| AS root.db.** |
| |
| ... |
| ``` |
| |
| ##### 3.4.2.2 为每一个测点建一个表 |
| |
| **优点**:查询某一个测点值时,不需要先查一下数据类型,再去决定查询哪张表,简单便捷 |
| |
| **缺点**:当测点数量较多时,会引入过多的表视图,需要写大量的建视图语句 |
| |
|  |
| |
| **表视图的创建 SQL:** |
| |
| ```SQL |
| CREATE VIEW viewdb.DCS_PIT_02105A |
| ( |
| value FLOAT FIELD |
| ) |
| AS root.db.DCS_PIT_02105A.** |
| |
| CREATE VIEW viewdb.DCS_PIT_02105B |
| ( |
| value DOUBLE FIELD |
| ) |
| AS root.db.DCS_PIT_02105B.** |
| |
| CREATE VIEW viewdb.DCS_XI_02716A |
| ( |
| value INT64 FIELD |
| ) |
| AS root.db.DCS_XI_02716A.** |
| |
| ...... |
| ``` |