diff --git a/docs/zh/05-basic/01-model.md b/docs/zh/05-basic/01-model.md index fc5c3a0a2e..0f01fbf562 100644 --- a/docs/zh/05-basic/01-model.md +++ b/docs/zh/05-basic/01-model.md @@ -77,6 +77,22 @@ toc_max_heading_level: 4 ![数据模型示意图](./data-model.png) +### 虚拟表 + +“一个设备一张表”的设计解决了工业和物联网等场景下的大多数时序数据管理和分析难题,但是在遇到更复杂的场景时,这种设计受到了设备复杂性的挑战。这种复杂性的根源在于一个设备无法简单的用一个或一组数据采集点来描述或管理,而业务分析往往需要综合多个或多组采集点的数据才能完成。以汽车或发电风机为例,整个设备(汽车或风机)中含有非常大量的传感器(数据采集点),这些传感器的输出和采集频率千差万别。一个超级表只能描述其中一种传感器,当需要综合多个传感器的数据进行分析计算时,只能通过多级关联查询的方式来进行,而这往往会导致易用性和性能方面的问题。 + +为了解决这个问题,TDengine 引入虚拟表(Virtual Table,简称为 VTable)的概念。虚拟表是一种不存储实际数据而可以用于分析计算的表,它的数据来源为其它真实存储数据的子表、普通表,通过将不同列数据按照时间戳排序、对齐、合并的方式来生成虚拟表。同真实表类似,虚拟表也可以分为虚拟超级表、虚拟子表、虚拟普通表。虚拟超级表可以是一个设备或一组分析计算所需数据的完整集合,每个虚拟子表可以根据需要引用相同或不同的列,因此可以灵活地根据业务需要进行定义,最终可以达到千表千面的效果。虚拟表不能写入、删除数据,在查询使用上同真实表基本相同,支持虚拟超级表、虚拟子表、虚拟普通表上的任何查询。唯一的区别在于虚拟表的数据是每次查询计算时动态生成的,只有一个查询中引用的列才会被合并进虚拟表中,因此同一个虚拟表在不同的查询中所呈现的数据可能是不同的。 + +虚拟超级表的主要功能特点包括: +1. 列选择与拼接
+ 用户可以从多个原始表中选择指定的列,按需组合到一张虚拟表中,形成统一的数据视图。 +2. 基于时间戳对齐
+ 以时间戳为依据对数据进行对齐,如果多个表在相同时间戳下存在数据,则对应列的值组合成同一行;若部分表在该时间戳下无数据,则对应列填充为 NULL。 +3. 动态更新
+ 虚拟表根据原始表的数据变化自动更新,确保数据的实时性。虚拟表不需实际存储,计算在生成时动态完成。 + +通过引入虚拟表的概念,现在 TDengine 可以非常方便的管理更大更复杂的设备数据。无论每个采集点如何建模(单列 or 多列),无论这些采集点的数据是分布在一个或多个库中,我们现在都可以通过定义虚拟子表的方式跨库跨表任意指定数据源,通过虚拟超级表的方式进行跨设备、跨分析的聚合运算,从此“一个设备一张表”彻底成为现实。 + ### 库 库是 TDengine 中用于管理一组表的集合。TDengine 允许一个运行实例包含多个库,并且每个库都可以配置不同的存储策略。由于不同类型的数据采集点通常具有不同的数据特征,如数据采集频率、数据保留期限、副本数量、数据块大小等。为了在各种场景下确保 TDengine 能够发挥最大效率,建议将具有不同数据特征的超级表创建在不同的库中。 @@ -93,6 +109,7 @@ toc_max_heading_level: 4 在查询数据时,TDengine 客户端会根据应用程序当前的时区设置,自动将保存的 UTC 时间戳转换成本地时间进行显示,确保用户在不同时区下都能看到正确的时间信息。 + ## 数据建模 本节用智能电表做例子,简要的介绍如何在 TDengine 里使用 SQL 创建数据库、超级表、表的基本操作。 @@ -215,3 +232,177 @@ TDengine 支持灵活的数据模型设计,包括多列模型和单列模型 尽管 TDengine 推荐使用多列模型,因为这种模型在写入效率和存储效率方面通常更优,但在某些特定场景下,单列模型可能更为适用。例如,当一个数据采集点的采集量种类经常发生变化时,如果采用多列模型,就需要频繁修改超级表的结构定义,这会增加应用程序的复杂性。在这种情况下,采用单列模型可以简化应用程序的设计和管理,因为它允许独立地管理和扩展每个物理量的超级表。 总之,TDengine 提供了灵活的数据模型选项,用户可以根据实际需求和场景选择最适合的模型,以优化性能和管理复杂性。 + +### 创建虚拟表 + +无论是选择单列模型还是多列模型,TDengine 都可以通过使用虚拟表进行跨表的运算。为智能电表为例,这里介绍虚拟表的两种使用场景: + +1. 单源多维度时序聚合 +2. 跨源采集量对比分析 + +#### 单源多维度时序聚合 +在单源多维度时序聚合场景中,“单源”并非指单一物理表,而是指来自**同一数据采集点**下的多个单列时序数据表。这些数据因业务需求或其他限制被拆分为多个单列存储的表,但通过设备标签和时间基准保持逻辑一致性。虚拟表在此场景中的作用是将一个采集点中“纵向“拆分的数据,还原为完整的“横向”状态。 +例如,在建模时采用了单列模型,对于电流、电压和相位这 3 种物理量,分别建立 3 张超级表。在这种场景下,用户可以通过虚拟表将这 3 种不同的采集量聚合到一张表中,以便进行统一的查询和分析。 + +创建单列模型的超级表的 SQL 如下: + +```sql + +CREATE STABLE current_stb ( + ts timestamp, + current float +) TAGS ( + device_id varchar(64), + location varchar(64), + group_id int +); + +CREATE STABLE voltage_stb ( + ts timestamp, + voltage int +) TAGS ( + device_id varchar(64), + location varchar(64), + group_id int +); + +CREATE STABLE phase_stb ( + ts timestamp, + phase float +) TAGS ( + device_id varchar(64), + location varchar(64), + group_id int +); +``` + +假设分别有 d1001,d1002,d1003,d1004 四个设备,分别对四个设备的电流、电压、相位采集量创建子表,SQL 如下: + +```sql +create table current_d1001 using current_stb(deviceid, location, group_id) tags("d1001", "California.SanFrancisco", 2); +create table current_d1002 using current_stb(deviceid, location, group_id) tags("d1002", "California.SanFrancisco", 3); +create table current_d1003 using current_stb(deviceid, location, group_id) tags("d1003", "California.LosAngeles", 3); +create table current_d1004 using current_stb(deviceid, location, group_id) tags("d1004", "California.LosAngeles", 2); + +create table voltage_d1001 using voltage_stb(deviceid, location, group_id) tags("d1001", "California.SanFrancisco", 2); +create table voltage_d1002 using voltage_stb(deviceid, location, group_id) tags("d1002", "California.SanFrancisco", 3); +create table voltage_d1003 using voltage_stb(deviceid, location, group_id) tags("d1003", "California.LosAngeles", 3); +create table voltage_d1004 using voltage_stb(deviceid, location, group_id) tags("d1004", "California.LosAngeles", 2); + +create table phase_d1001 using phase_stb(deviceid, location, group_id) tags("d1001", "California.SanFrancisco", 2); +create table phase_d1002 using phase_stb(deviceid, location, group_id) tags("d1002", "California.SanFrancisco", 3); +create table phase_d1003 using phase_stb(deviceid, location, group_id) tags("d1003", "California.LosAngeles", 3); +create table phase_d1004 using phase_stb(deviceid, location, group_id) tags("d1004", "California.LosAngeles", 2); +``` + +此时想要通过一张虚拟超级表来讲这三种采集量聚合到一张表中,创建虚拟超级表 SQL 如下: + +```sql +CREATE STABLE meters_v ( + ts timestamp, + current float, + voltage int, + phase float +) TAGS ( + location varchar(64), + group_id int +) VIRTUAL 1; +``` + +并且对四个设备 d1001,d1002,d1003,d1004 分别创建虚拟子表,SQL 如下: + +```sql +CREATE VTABLE d1001_v ( + current from current_d1001.current, + voltage from voltage_d1001.voltage, + phase from phase_d1001.phase +) +USING meters_v +TAGS ( + "California.SanFrancisco", + 2 +); + +CREATE VTABLE d1002_v ( + current from current_d1002.current, + voltage from voltage_d1002.voltage, + phase from phase_d1002.phase +) +USING meters_v +TAGS ( + "California.SanFrancisco", + 3 +); + +CREATE VTABLE d1003_v ( + current from current_d1003.current, + voltage from voltage_d1003.voltage, + phase from phase_d1003.phase +) +USING meters_v +TAGS ( + "California.LosAngeles", + 3 +); + +CREATE VTABLE d1004_v ( + current from current_d1004.current, + voltage from voltage_d1004.voltage, + phase from phase_d1004.phase +) +USING meters_v +TAGS ( + "California.LosAngeles", + 2 +); +``` + +以设备 d1001 为例,假设 d1001 设备的电流、电压、相位数据如下: + +![data-model-origin-table.png](data-model-origin-table.png) + +虚拟表 d1001_v 中的数据如下 : + +| Timestamp | Current | Voltage | Phase | +|:--------------:|:-------:|:---------:|:-------:| +| 1538548685000 | 10.3 | 219 | 0.31 | +| 1538548695000 | 12.6 | 218 | 0.33 | +| 1538548696800 | 12.3 | 221 | 0.31 | +| 1538548697100 | 12.1 | 220 | NULL | +| 1538548697200 | NULL | NULL | 0.32 | +| 1538548697700 | 11.8 | NULL | NULL | +| 1538548697800 | NULL | 222 | 0.33 | + +#### 跨源采集量对比分析 + +在跨源采集量对比分析中,“跨源”指数据来自**不同数据采集点**。在不同数据采集点中提取具有可比语义的采集量,通过虚拟表将这些采集量按照时间戳进行对齐和合并,并进行对比分析。 +例如,用户可以将来自不同设备的电流数据聚合到一张虚拟表中,以便进行电流数据的对比分析。 + +以分析 d1001, d1002, d1003, d1004 四个设备的电流数据为例,创建虚拟表的 SQL 如下: + +```sql +CREATE VTABLE current_v ( + ts timestamp, + d1001_current float from current_d1001.current, + d1002_current float from current_d1002.current, + d1003_current float from current_d1003.current, + d1004_current float from current_d1004.current +); +``` + +假设 d1001, d1002, d1003, d1004 四个设备的电流数据如下: + +![data-model-origin-table-2.png](data-model-origin-table-2.png) + +虚拟表 current_v 中的数据如下: + +| Timestamp | d1001_current | d1002_current | d1003_current | d1004_current | +|:--------------:|:-------------:|:-------------:|:-------------:|:-------------:| +| 1538548685000 | 10.3 | 11.7 | 11.2 | 12.4 | +| 1538548695000 | 12.6 | 11.9 | 10.8 | 11.3 | +| 1538548696800 | 12.3 | 12.4 | 12.3 | 10.1 | +| 1538548697100 | 12.1 | NULL | 11.1 | NULL | +| 1538548697200 | NULL | 12.2 | NULL | 11.7 | +| 1538548697700 | 11.8 | 11.4 | NULL | NULL | +| 1538548697800 | NULL | NULL | 12.1 | 12.6 | + diff --git a/docs/zh/05-basic/data-model-origin-table-2.png b/docs/zh/05-basic/data-model-origin-table-2.png new file mode 100644 index 0000000000..8d0e203b4e Binary files /dev/null and b/docs/zh/05-basic/data-model-origin-table-2.png differ diff --git a/docs/zh/05-basic/data-model-origin-table.png b/docs/zh/05-basic/data-model-origin-table.png new file mode 100644 index 0000000000..4e128e26b0 Binary files /dev/null and b/docs/zh/05-basic/data-model-origin-table.png differ diff --git a/docs/zh/14-reference/03-taos-sql/04-stable.md b/docs/zh/14-reference/03-taos-sql/04-stable.md index 98dad1a2e4..5412e6d129 100644 --- a/docs/zh/14-reference/03-taos-sql/04-stable.md +++ b/docs/zh/14-reference/03-taos-sql/04-stable.md @@ -22,6 +22,7 @@ table_option: { COMMENT 'string_value' | SMA(col_name [, col_name] ...) | KEEP value + | VIRTUAL {0 | 1} } ``` @@ -36,6 +37,7 @@ table_option: { 4. 关于 `ENCODE` 和 `COMPRESS` 的使用,请参考 [按列压缩](../compress) 5. 关于 table_option 中的参数说明,请参考 [建表 SQL 说明](../table) 6. 关于 table_option 中的 keep 参数,仅对超级表生效,keep 参数的详细说明可以参考 [数据库说明](02-database.md),唯一不同的是超级表 keep 不会立即影响查询结果,仅在 compact 后生效。 +7. 关于 table_option 中的 virtual 参数,仅对超级表生效,指定为 1 表示创建虚拟超级表,为 0 表示创建超级表,默认为 0。创建虚拟超级表时,column_definition 中只支持 type_name 选项,不支持定义额外主键列以及压缩选项。 ## 查看超级表 diff --git a/docs/zh/14-reference/03-taos-sql/22-meta.md b/docs/zh/14-reference/03-taos-sql/22-meta.md index 2e583a36b2..e947c06bac 100644 --- a/docs/zh/14-reference/03-taos-sql/22-meta.md +++ b/docs/zh/14-reference/03-taos-sql/22-meta.md @@ -151,18 +151,19 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数 提供用户创建的超级表的相关信息。 -| # | **列名** | **数据类型** | **说明** | -| --- | :-----------: | ------------ | ----------------------------------------------------------------------------------------------------- | -| 1 | stable_name | VARCHAR(192) | 超级表表名 | -| 2 | db_name | VARCHAR(64) | 超级表所在的数据库的名称 | -| 3 | create_time | TIMESTAMP | 创建时间 | -| 4 | columns | INT | 列数目 | -| 5 | tags | INT | 标签数目。需要注意,`tags` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | -| 6 | last_update | TIMESTAMP | 最后更新时间 | -| 7 | table_comment | VARCHAR(1024) | 表注释 | -| 8 | watermark | VARCHAR(64) | 窗口的关闭时间。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | -| 9 | max_delay | VARCHAR(64) | 推送计算结果的最大延迟。需要注意,`max_delay` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。| -| 10 | rollup | VARCHAR(128) | rollup 聚合函数。需要注意,`rollup` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | +| # | **列名** | **数据类型** | **说明** | +|----|:-------------:|---------------|-----------------------------------------------------------------| +| 1 | stable_name | VARCHAR(192) | 超级表表名 | +| 2 | db_name | VARCHAR(64) | 超级表所在的数据库的名称 | +| 3 | create_time | TIMESTAMP | 创建时间 | +| 4 | columns | INT | 列数目 | +| 5 | tags | INT | 标签数目。需要注意,`tags` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | +| 6 | last_update | TIMESTAMP | 最后更新时间 | +| 7 | table_comment | VARCHAR(1024) | 表注释 | +| 8 | watermark | VARCHAR(64) | 窗口的关闭时间。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | +| 9 | max_delay | VARCHAR(64) | 推送计算结果的最大延迟。需要注意,`max_delay` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | +| 10 | rollup | VARCHAR(128) | rollup 聚合函数。需要注意,`rollup` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | +| 11 | virtual | BOOL | 超级表是否是虚拟超级表。 | ## INS_TABLES @@ -194,17 +195,18 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数 ## INS_COLUMNS -| # | **列名** | **数据类型** | **说明** | -| --- | :-----------: | ------------ | ---------------------- | -| 1 | table_name | VARCHAR(192) | 表名 | -| 2 | db_name | VARCHAR(64) | 该表所在的数据库的名称 | -| 3 | table_type | VARCHAR(21) | 表类型 | -| 4 | col_name | VARCHAR(64) | 列 的名称 | -| 5 | col_type | VARCHAR(32) | 列 的类型 | -| 6 | col_length | INT | 列 的长度 | -| 7 | col_precision | INT | 列 的精度 | -| 8 | col_scale | INT | 列 的比例 | -| 9 | col_nullable | INT | 列 是否可以为空 | +| # | **列名** | **数据类型** | **说明** | +|----|:-------------:|--------------|---------------------------------------------------------------| +| 1 | table_name | VARCHAR(192) | 表名 | +| 2 | db_name | VARCHAR(64) | 该表所在的数据库的名称 | +| 3 | table_type | VARCHAR(21) | 表类型 | +| 4 | col_name | VARCHAR(64) | 列 的名称 | +| 5 | col_type | VARCHAR(32) | 列 的类型 | +| 6 | col_length | INT | 列 的长度 | +| 7 | col_precision | INT | 列 的精度 | +| 8 | col_scale | INT | 列 的比例 | +| 9 | col_nullable | INT | 列 是否可以为空 | +| 10 | col_source | VARCHAR(322) | 列 的数据来源。只有虚拟表的列才会有该值,表示虚拟表的数据来源,为 db_name.table_name.col_name | ## INS_USERS diff --git a/docs/zh/14-reference/03-taos-sql/34-virtualtable.md b/docs/zh/14-reference/03-taos-sql/34-virtualtable.md new file mode 100644 index 0000000000..a243169a0a --- /dev/null +++ b/docs/zh/14-reference/03-taos-sql/34-virtualtable.md @@ -0,0 +1,311 @@ +--- +sidebar_label: 虚拟表 +title: 虚拟表 +description: 对虚拟表的各种管理操作 +--- +## 创建虚拟表 + +`CREATE VTABLE` 语句用于创建普通虚拟表和以虚拟超级表为模板创建虚拟子表。 + +### 创建虚拟超级表 + +见 [创建超级表](./04-stable.md#创建超级表) 中的 `VIRTUAL` 参数。 + +### 创建虚拟普通表 +```sql +CREATE VTABLE [IF NOT EXISTS] [db_name].vtb_name + ts_col_name timestamp, + (create_defination[ ,create_defination] ...) + + create_definition: + vtb_col_name column_definition + +column_definition: + type_name [FROM [db_name.]table_name.col_name] + +``` + +### 创建虚拟子表 +```sql +CREATE VTABLE [IF NOT EXISTS] [db_name].vtb_name + (create_defination[ ,create_defination] ...) + USING [db_name.]stb_name + [(tag_name [, tag_name] ...)] + TAGS (tag_value [, tag_value] ...) + + create_definition: + [stb_col_name FROM] [db_name.]table_name.col_name + tag_value: + const_value +``` + +**使用说明** + +1. 虚拟表(列)名命名规则参见 [名称命名规则](./19-limit.md#名称命名规则)。 +2. 表名最大长度为 192。 +3. 表的第一个字段必须是 TIMESTAMP,并且系统自动将其设为主键。 +4. 表的每行长度不能超过 64KB(注意:每个 VARCHAR/NCHAR/GEOMETRY 类型的列还会额外占用 2 个字节的存储位置)。 +5. 使用数据类型 VARCHAR/NCHAR/GEOMETRY,需指定其最长的字节数,如 VARCHAR(20),表示 20 字节。 +6. 创建虚拟表时使用 FROM 来指定列的数据源,支持使用 db_name 跨库指定数据源,不指定 db_name 时默认使用当前 use 的数据库,若不指定 db_name 且未 use 数据库,则会报错。 +7. 创建虚拟表时不显式的指定 ts 列的数据源,ts 列的取值是查询虚拟表时查询语句中包含的所有列对应的原始表的主键时间戳合并的结果。 +8. 虚拟超级表下只支持创建虚拟子表,虚拟子表也只能以虚拟超级表为模版来创建。 +9. 创建虚拟表时需要保证虚拟表中的列、标签和指定的数据来源列、标签的数据类型相同,否则会报错。 +10. 在同一个数据库内,虚拟表名称不允许重名,虚拟表名和表名也不允许重名。虚拟表名和视图名允许重名(不推荐)当出现视图与虚拟表名重名时,写入、查询、授权、回收权限等操作优先使用同名表。 +11. 创建虚拟子表和虚拟普通表时,使用 FROM 指定某一列的数据来源时,该列只能来源于普通子表或普通表,不支持来源于超级表、视图或其他虚拟表。也不支持来源于有复合主键的表。 + +## 查询虚拟表 + +虚拟表与正常表无论是查询语法还是范围都没有区别,不同之处在于虚拟表所呈现的数据集在不同的查询中可能是不相同的,具体可以参考虚拟表数据生成规则。 + +### 虚拟表数据生成规则 + +1. 虚拟表以时间戳为基准,对多个原始表的数据进行对齐。 +2. 如果多个原始表在相同时间戳下有数据,则这些列的值组合成同一行;否则,对于缺失的列,填充 NULL。 +3. 虚拟表的时间戳的值是查询中包含的所有列所在的原始表的时间戳的并集,因此当不同查询选择列不同时可能出现结果集行数不一样的情况。 +4. 用户可以从多个表中选择任意列进行组合,未选择的列不会出现在虚拟表中。 + +**示例** + +假设有表 t1, t2, t3 结构和数据如下: + +![virtual-table-origin-table.png](pic/virtual-table-origin-table.png) + +并且有虚拟普通表 v1 ,创建方式如下: + +```sql +create vtable v1 ( + ts timestamp, + c1 int from t1.value, + c2 int from t2.value, + c3 int from t3.value1, + c4 int from t3.value2); +``` + +那么根据虚拟表对于多表数据的整合规则,执行如下查询时: + +```sql +select * from v1; +``` + +结果如下: + +![virtual-table-query-res.png](pic/virtual-table-query-res.png) + +如果没有选择全部列,只是选择了部分列,查询的结果只会包含选择的列的原始表的时间戳,例如执行如下查询: + +```sql +select c1, c2 from v1; +``` + +得到的结果如下图所示: + +![virtual-table-query-res-part.png](pic/virtual-table-query-res-part.png) + +因为 c1, c2 列对应的原始表 t1, t2 中没有 0:00:03 这个时间戳,所以最后的结果也不会包含这个时间戳。 + +**使用限制** + +1. 查询虚拟超级表时,暂不支持虚拟子表的数据源来自不同的数据库。 + +## 修改虚拟普通表 + +```sql +ALTER VTABLE [db_name.]vtb_name alter_table_clause + +alter_table_clause: { + ADD COLUMN vtb_col_name vtb_column_type [FROM table_name.col_name] + | DROP COLUMN vtb_col_name + | ALTER COLUMN vtb_col_name SET {table_name.col_name | NULL } + | MODIFY COLUMN col_name column_type + | RENAME COLUMN old_col_name new_col_name +} +``` + +**使用说明** +对虚拟普通表可以进行如下修改操作 + +1. ADD COLUMN:添加列。 +2. DROP COLUMN:删除列。 +3. MODIFY COLUMN:修改列定义,如果数据列的类型是可变长类型,那么可以使用此指令修改其宽度,只能改大,不能改小。如果虚拟表该列已指定数据源,那么修改列宽会因为修改后的列宽和数据源的列宽不匹配而报错,可以先将数据源置为空后再修改列宽。 +4. RENAME COLUMN:修改列名称。 +5. ALTER COLUMN .. SET:修改列的数据源。 SET NULL 表示将虚拟表某列的数据源置为空。 + +### 增加列 + +```sql +ALTER VTABLE vtb_name ADD COLUMN vtb_col_name vtb_col_type [FROM [db_name].table_name.col_name] +``` + +### 删除列 + +```sql +ALTER VTABLE vtb_name DROP COLUMN vtb_col_name +``` + +### 修改列宽 + +```sql +ALTER VTABLE vtb_name MODIFY COLUMN vtb_col_name data_type(length); +``` + +### 修改列名 + +```sql +ALTER VTABLE vtb_name RENAME COLUMN old_col_name new_col_name +``` + +### 修改列的数据源 + +```sql +ALTER VTABLE vtb_name ALTER COLUMN vtb_col_name SET {[db_name.]table_name.col_name | NULL} +``` + +## 修改虚拟子表 + +```sql +ALTER VTABLE [db_name.]vtb_name alter_table_clause + +alter_table_clause: { + ALTER COLUMN vtb_col_name SET table_name.col_name + | SET TAG tag_name = new_tag_value +} +``` + +**使用说明** + +1. 对虚拟子表的列和标签的修改,除了更改标签值以外,都要通过虚拟超级表才能进行。 + +### 修改虚拟子表标签值 + +```sql +ALTER VTABLE tb_name SET TAG tag_name1=new_tag_value1, tag_name2=new_tag_value2 ...; +``` + +### 修改列的数据源 + +```sql +ALTER VTABLE vtb_name ALTER COLUMN vtb_col_name SET {[db_name.]table_name.col_name | NULL} +``` + +## 删除虚拟表 + +```sql +DROP VTABLE [IF EXISTS] [dbname].vtb_name; +``` + +## 查看虚拟表的信息 + +### 显示某个数据库下所有虚拟表 + +如下 SQL 语句可以列出当前数据库中的所有虚拟表名。 + +```sql +SHOW [NORMAL | CHILD] [db_name.]VTABLES [LIKE 'pattern']; +``` + +**使用说明** + +1. 如果没有指定 db_name, 显示当前数据库下的所有虚拟普通表和虚拟子表的信息。若没有使用数据库并且没有指定 db_name, 则会报错 database not specified。可以使用 LIKE 对表名进行模糊匹配。NORMAL 指定只显示虚拟普通表信息, CHILD 指定只显示虚拟子表信息。 + +### 显示虚拟表创建语句 + +```sql +SHOW CREATE VTABLE [db_name.]vtable_name; +``` + +显示 vtable_name 指定的虚拟表的创建语句。支持虚拟普通表和虚拟子表。常用于数据库迁移。对一个已经存在的虚拟表,返回其创建语句;在另一个集群中执行该语句,就能得到一个结构完全相同的虚拟表。 + +### 获取虚拟表结构信息 + +```sql +DESCRIBE [db_name.]vtb_name; +``` + +### 查看所有虚拟表信息 + +```sql +SELECT ... FROM information_schema.ins_tables where type = 'VIRTUAL_NORMAL_TABLE' or type = 'VIRTUAL_CHILD_TABLE'; +``` + +## 写入虚拟表 + +不支持向虚拟表中写入数据,以及不支持删除虚拟表中的数据。虚拟表只是对原始表进行运算后的计算结果,是一张逻辑表,因此只能对其进行查询,不可以写入或删除数据。 + + +## 虚拟表与视图 + +虚拟表与视图看起来相似,但是有很多不同点: + +| 属性 |虚拟表 (Virtual Table) |视图 (View)| +|----------------|------------------------|-----------| +| 定义 |虚拟表是一种动态数据结构,根据多表的列和时间戳组合规则生成逻辑表。 |视图是一种基于 SQL 查询的虚拟化表结构,用于保存查询逻辑的定义。| +| 数据来源 |来自多个原始表,可以动态选择列,并通过时间戳对齐数据。 |来自单个或多个表的查询结果,通常是一个复杂的 SQL 查询。| +| 数据存储 |不实际存储数据,所有数据在查询时动态生成。 |不实际存储数据,仅保存 SQL 查询逻辑。| +| 时间戳处理 |通过时间戳对齐将不同表的列整合到统一的时间轴上。| 不支持时间戳对齐,数据由查询逻辑直接决定。| +| 更新机制 |动态更新,原始表数据变更时,虚拟表数据实时反映变化。| 动态更新,但依赖于视图定义的查询逻辑,不涉及对齐或数据整合。| +| 功能特性 |支持空值填充和插值(如 prev、next、linear)。 |不支持内置填充和插值功能,需通过查询逻辑自行实现。| +| 应用场景 |时间序列对齐、跨表数据整合、多源数据对比分析等场景。| 简化复杂查询逻辑、限制用户访问、封装业务逻辑等场景。| +| 性能 |由于多表对齐和空值处理,查询复杂度可能较高,尤其在数据量大时。| 性能通常取决于视图的查询语句复杂度,与单表查询性能相似。| + +不支持虚拟表和视图之间的相互转化,如根据虚拟表建立视图或者根据视图建立虚拟表。 + +## 虚拟表的权限 + +### 权限说明 + +虚拟表的权限分为 READ、WRITE 两种,查询操作需要具备 READ 权限,对虚拟表本身的删除和修改操作需要具备 WRITE 权限。 + +### 语法 + +#### 授权 + +```sql +GRANT privileges ON [db_name.]vtable_name TO user_name +privileges: { + ALL, + | priv_type [, priv_type] ... +} +priv_type: { + READ + | WRITE +} +``` + +#### 回收权限 + +```sql +REVOKE privileges ON [db_name.]vtable_name FROM user_name +privileges: { + ALL, + | priv_type [, priv_type] ... +} +priv_type: { + READ + | WRITE +} +``` + +### 权限规则 + +1. 虚拟表的创建者和 root 用户默认具备所有权限。 +2. 用户可以通过 dbname.vtbname 来为指定的虚拟表表(包括虚拟超级表和虚拟普通表)授予或回收其读写权限,不支持直接对虚拟子表授予或回收权限。 +3. 虚拟子表和虚拟超级表不支持基于标签的授权(表级授权),虚拟子表继承虚拟超级表的权限。 +4. 对其他用户进行授权与回收权限可以通过 GRANT 和 REVOKE 语句进行,该操作只能由 root 用户进行。 +5. 具体相关权限控制细则总结如下: + +| 序号 | 操作 | 权限要求 | +|------|------|----------------------------------------------------------| +| 1 | CREATE VTABLE | 用户对虚拟表所属数据库有 WRITE 权限 且
用户对虚拟表的数据源对应的原始表有 READ 权限。 | +| 2 | DROP/ALTER VTABLE | 用户对虚拟表有 WRITE 权限,若要指定某一列的数据源,需要同时对数据源对应的原始表有 READ 权限。 | +| 3 |SHOW VTABLES | 无 | +| 4 | SHOW CREATE VTABLE | 无 | +| 5 | DESCRIBE VTABLE | 无 | +| 6 | 系统表查询 | 无 | +| 7 | SELECT FROM VTABLE | 操作用户对虚拟表有 READ 权限 | +| 8 | GRANT/REVOKE | 只有 root 用户有权限 | + +## 使用场景 + +| SQL 查询 | SQL 写入 | STMT 查询 | STMT 写入 | 订阅 | 流计算 | +|---------|--------|---------|------|--------|---| +| 支持 | 不支持 | 不支持 | 不支持 | 不支持 | 支持 | \ No newline at end of file diff --git a/docs/zh/14-reference/03-taos-sql/pic/virtual-table-origin-table.png b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-origin-table.png new file mode 100644 index 0000000000..4819389b22 Binary files /dev/null and b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-origin-table.png differ diff --git a/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res-part.png b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res-part.png new file mode 100644 index 0000000000..5afbdac55e Binary files /dev/null and b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res-part.png differ diff --git a/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res.png b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res.png new file mode 100644 index 0000000000..d32e15cb3f Binary files /dev/null and b/docs/zh/14-reference/03-taos-sql/pic/virtual-table-query-res.png differ