news 2026/9/12 23:51:02

TDengine Supertable 完整指南:从 CREATE STABLE 到 ALTER STABLE 的建模、查询与运维

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TDengine Supertable 完整指南:从 CREATE STABLE 到 ALTER STABLE 的建模、查询与运维

TDengine Supertable 完整指南:从 CREATE STABLE 到 ALTER STABLE 的建模、查询与运维

【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine

TDengine 的超级表(Supertable)是一套将**表结构(Schema)标签(Tags)**分离的数据建模机制:同一类设备/采集点的共性测点定义为列(Metric),设备的静态属性定义为标签(Tag),通过"一个超级表 + 大量子表(Subtable)"的模式承载海量时序设备数据。本文以 Supertables 文档为骨架,结合 TDengine 仓库中的语法解析器(sql.y)、元数据校验实现(mndStb.c)与自动化测试用例,系统讲解超级表的创建、查看、删除、修改与查询,并深入说明复合主键、表级 KEEP、虚拟超级表等进阶能力。读完本文,你将能够独立完成超级表的全生命周期建模、按标签批量管理子表、并通过ALTER STABLE安全演进表结构。

一、超级表是什么:模型与核心概念

在 TDengine 中,一张超级表由以下三部分构成:

  • 列(Metric / 数据列):描述采集数据本身的测点,如电压、电流、温度,所有子表共享同一组列定义;
  • 时间戳主键:每张表的第一列必须是TIMESTAMP,系统自动将其设为主键;
  • 标签(Tag):描述设备的静态维度信息,如设备 ID、地理位置、厂商,用于快速过滤与聚合。

创建超级表后,业务侧通过CREATE TABLE ... USING stb_name TAGS (...)以超级表为模板批量创建子表,每张子表拥有完整列结构 + 一份独立的标签值。数据写入子表,查询既可以按子表进行,也可以在超级表上跨子表做投影与聚合(详见 Tables 中的子表创建语法)。

从仓库源码看,CREATE STABLECREATE TABLE在语法层面共用一套列定义解析,但通过一个布尔标记区分:在 sql.y 中,CREATE TABLE ... tags_def_optcreateCreateTableStmt(pCxt, A, false, ...),而CREATE STABLE ... tags_defcreateCreateTableStmt(pCxt, A, true, ...)——true即表示创建的是超级表。

二、创建超级表(CREATE STABLE)

2.1 完整语法

CREATE STABLE [IF NOT EXISTS] [db_name.]stb_name (create_definition [, create_definition] ...) TAGS (create_definition [, create_definition] ...) [BASE ON [db_name.]parent_stb_name [, [db_name.]parent_stb_name] ...] [table_options] create_definition: col_name column_definition column_definition: type_name [COMPOSITE KEY] [ENCODE 'encode_type'] [COMPRESS 'compress_type'] [LEVEL 'level_type'] table_options: table_option ... table_option: { COMMENT 'string_value' | SMA(col_name [, col_name] ...) | KEEP value | VIRTUAL {0 | 1} }

2.2 一个最小可用示例

CREATE DATABASE power; USE power; CREATE STABLE meters ( ts TIMESTAMP, voltage FLOAT, current FLOAT ) TAGS ( location BINARY(20), group_id INT );

以上语句创建一个用于智能电表场景的超级表meters,随后即可批量创建子表:

CREATE TABLE d1001 USING meters TAGS ('California.SanFrancisco', 2); CREATE TABLE d1002 USING meters TAGS ('California.LosAngeles', 2);

2.3 命名与基础约束

  • 超级表名、列名、标签名的命名规则与普通表一致,详见 Naming Rules:合法字符为英文字母、数字、下划线,必须以字母或下划线开头,大小写不敏感,不能使用保留关键字;如需更自由的命名可用反引号转义。
  • 超级表最多 4096 列(含标签列);虚拟超级表最多 32767 个数据列,标签列仍以 128 个为上限。
  • 超级表至少包含 3 列:一个时间戳列(主键列)、一个测点列、一个标签列。
  • 第一列必须是TIMESTAMP类型,系统自动将其设为主键。

上述限制在源码中有直接对应。在 tdef.h 中:

#define TSDB_MAX_COLUMNS 32767 // 虚拟表 / 虚拟超级表的最大列数 #define TSDB_MAX_COLUMNS_NON_VIRTUAL 4096 // 普通超级表的最大列数 #define TSDB_MIN_COLUMNS 2 // PRIMARY COLUMN(timestamp) + other columns

而 mndStb.c 的 mndCheckCreateStbReq 在创建请求校验时依次检查:numOfColumns + numOfTags不得超过上限、标签数必须 ≥1 且 ≤128、第一列必须是TSDB_DATA_TYPE_TIMESTAMP,任何一项不满足都会返回对应的TSDB_CODE_*错误。这也解释了为什么"至少三列"中的两列下限来自TSDB_MIN_COLUMNS(时间戳 + 1 测点)再加至少 1 个标签。

2.4 COMPOSITE KEY:复合主键

默认情况下,时间戳是唯一主键。通过COMPOSITE KEY关键字,可以为超级表指定第二主键列,与时间戳共同构成复合主键:

CREATE STABLE sensor_data ( ts TIMESTAMP, device_id INT COMPOSITE KEY, value FLOAT ) TAGS (region VARCHAR(16));

复合主键列的类型限制:

  • 整数类型:INTBIGINTINT UNSIGNEDBIGINT UNSIGNED
  • 字符串类型:VARCHARBINARY

去重语义:当超级表带有复合主键时,只有当时间戳列和第二主键列同时相同,两条记录才被视为重复记录,此时数据库只保留最新的一条;否则两条记录都会保留。

2.5 ENCODE / COMPRESS / LEVEL:列级编码与压缩

ENCODECOMPRESSLEVEL三个选项用于在创建列时按列配置一级编码(Encoding)与二级压缩(Compression)算法,完整算法矩阵与默认值见 Data Compression。核心要点:

  • 一级压缩(编码)simple8bbit-packingdelta-idelta-dbss(字节流拆分)、disabled
  • 二级压缩lz4zlibzstdtszxzdisabled
  • 压缩级别high(压缩率最高、速度最慢)、low(速度最快、压缩率最低)、medium(均衡,默认),支持缩写'h'/'l'/'m'

示例:

CREATE STABLE telemetry ( ts TIMESTAMP, temp FLOAT ENCODE 'bss' COMPRESS 'zstd' LEVEL 'high', counter BIGINT ENCODE 'delta-i' COMPRESS 'lz4' ) TAGS (node_id INT);

注意:虚拟超级表(VIRTUAL 1)不支持ENCODECOMPRESS

2.6 TAGS 子句:标签列定义

TAGS子句定义超级表的标签列,有以下限制:

  • TIMESTAMP类型的标签列在插入时必须提供字面量时间戳值,不支持NOW + 10s这类算术表达式;
  • 标签列名必须在所有列中唯一,测点列与标签列不能同名
  • 标签列名不能使用保留关键字;
  • 超级表最多 128 个标签列,且至少 1 个标签列
  • 所有标签列的总长度不能超过 16 KB

这些限制同样能在 tdef.h 中找到常量定义:

#define TSDB_MAX_TAGS_LEN 16384 // 16 KB #define TSDB_MAX_TAGS 128

并在 mndCheckCreateStbReq 中做了运行时校验。

2.7 表级选项:COMMENT / SMA / KEEP / VIRTUAL

COMMENT:表注释,最大长度 1024 字节,可用于超级表、子表与普通表,详见 Tables。

SMA(Small Materialized Aggregates,小物化聚合):按数据块进行MAX/MIN/SUM的预计算,以加速聚合查询。默认情况下系统会对大多数列自动创建块级 SMA(BINARYNCHAR等类型不创建);若在创建时显式指定SMA(col_name, ...),则只为列出的列创建块级 SMA:

CREATE STABLE power ( ts TIMESTAMP, voltage FLOAT, current FLOAT, power FLOAT ) TAGS (loc VARCHAR(20)) SMA(voltage, current, power);

KEEP(数据保留期):与 Databases 中的库级KEEP语义类似,但存在三点重要差异:

  1. 超级表级KEEP必须小于数据库级KEEP
  2. 超级表级KEEP不会立即生效——必须先对数据库执行FLUSH再执行COMPACT,被超级表级KEEP标记为过期的数据才会被真正移除;
  3. 如果先 compact 数据库、再修改超级表级KEEP值、然后又 compact 一次,过期数据可能无法被完全清除

仓库中的自动化测试 test_stable_keep_compact.py 完整覆盖了这一行为:测试先创建带KEEP的数据库(DURATION {duration}h KEEP {keep}),再通过CREATE STABLE ... KEEP {keep_days}d创建表级 KEEP 的超级表,插入 1~7 天前的历史数据后执行 FLUSH + COMPACT 并验证过期数据是否被清除。测试中对KEEPDURATION的约束(keep > 3*duration)也印证了数据库创建时必须满足"KEEP 至少为 DURATION 的 3 倍"这一规则。

VIRTUAL(虚拟超级表)VIRTUAL 1表示创建虚拟超级表。虚拟表是逻辑表,本身不存储数据,查询时按虚拟表定义从一张或多张物理表/既有虚拟表中按时间戳对齐读取列数据并即时生成结果集。虚拟超级表作为虚拟子表的模板,有以下限制:

  • 不支持COMPOSITE KEY
  • 不支持压缩选项(ENCODE/COMPRESS);
  • 可通过BASE ON子句从一个或多个父虚拟超级表继承列与标签,详见 Virtual Supertable Inheritance。
CREATE STABLE p_device (ts timestamp, status int) TAGS (region int) VIRTUAL 1; CREATE STABLE p_temp (ts timestamp, temp float) TAGS (sensor_id int) BASE ON test_db.p_device VIRTUAL 1;

2.8 BASE ON:虚拟超级表继承

BASE ON子句用于虚拟超级表之间的继承,子虚拟超级表(VST)继承父 VST 的所有标签以及除主时间戳外的所有列,自身新增的列与标签追加在继承内容之后。约束包括:

  • BASE ON要求父子双方都必须是虚拟超级表(VIRTUAL 1);
  • 父子虚拟超级表必须位于同一个数据库
  • 子表自身的列/标签名不得与任何父表继承来的名称冲突;
  • 循环继承会被检测并拒绝;
  • 一个 VST 最多继承自10 个父 VST;
  • 已有子节点的非叶子 VST 无法直接在其下创建虚拟子表,也不能再作为BASE ON的目标;
  • 父 VST 一旦成为非叶子节点,其 Schema 即被冻结:ADD COLUMNDROP COLUMNADD TAGDROP TAGRENAME TAG及标签宽度修改都会被拒绝。

三、查看超级表

3.1 查看全部超级表

SHOW [db_name.]STABLES [LIKE 'pattern'];

db_name缺省时显示当前数据库下的超级表,LIKE支持模糊匹配。

3.2 查看超级表创建语句

SHOW CREATE STABLE [db_name.]stb_name;

返回该超级表原始的创建 SQL,常用于迁移或克隆已有超级表——在另一个集群中执行该语句即可得到结构完全一致的表。

3.3 查看超级表结构

DESCRIBE [db_name.]stb_name;

展示列的字段名、类型与压缩设置。

3.4 查看超级表下所有子表的标签

SHOW TABLE TAGS [tag_name [, tag_name] ...] FROM table_name [FROM db_name]; -- 或 SHOW TABLE TAGS [tag_name [, tag_name] ...] FROM [db_name.]table_name;

table_name既可以是子表(展示该子表标签),也可以是超级表名(此时展示其下所有子表及其标签)。实际输出示例:

taos> SHOW TABLE TAGS FROM st1; tbname | id | loc | ====================================================================== st1s1 | 1 | losangeles | st1s2 | 2 | sanfrancisco | st1s3 | 3 | sacramento | Query OK, 3 rows in database (0.004455s)

也可以只查看指定标签列:

taos> SELECT DISTINCT TBNAME, id FROM st1; tbname | id | =============================================== st1s1 | 1 | st1s2 | 2 | st1s3 | 3 | Query OK, 3 rows in database (0.002891s)

注意:此语句必须包含DISTINCTTBNAME,才能保证在数据缺失或数据集很大时结果准确且执行快速。

3.5 查看指定子表的标签

taos> SHOW TAGS FROM st1s1; table_name | db_name | stable_name | tag_name | tag_type | tag_value | ============================================================================================================ st1s1 | test | st1 | id | INT | 1 | st1s1 | test | st1 | loc | VARCHAR(20) | sanfrancisco | Query OK, 2 rows in database (0.003684s)

同样支持只查看指定标签:

taos> SELECT DISTINCT TBNAME, id, loc FROM st1s1; tbname | id | loc | ================================================== st1s1 | 1 | sanfrancisco | Query OK, 1 rows in database (0.001884s)

从语法层面看,SHOW TABLE TAGSSHOW TAGS FROM在解析器 sql.y 中是两条独立的文法规则,分别构造QUERY_NODE_SHOW_TAGS_STMTcreateShowTableTagsStmt,前者定位单张子表,后者支持通过tag_list_opt指定标签列并在超级表范围聚合输出。

四、删除超级表(DROP STABLE)

DROP STABLE [IF EXISTS] [db_name.]stb_name;

:::important 删除超级表会级联删除该超级表下创建的所有子表及其数据,务必谨慎操作。 :::

需要注意的是:删除超级表不会立即释放磁盘空间。超级表会立刻被标记为待删除,查询也不再返回该表的数据,但磁盘空间要等到操作系统自动回收,或用户手动COMPACT数据库后才会释放。这与 Tables 中普通表的删除语义一致。

五、修改超级表(ALTER STABLE)

5.1 完整语法

ALTER STABLE [db_name.]stb_name alter_table_clause alter_table_clause: { alter_table_options | ADD COLUMN col_name column_type | DROP COLUMN col_name | MODIFY COLUMN col_name column_type | ADD TAG tag_name tag_type | DROP TAG tag_name | MODIFY TAG tag_name tag_type | RENAME TAG old_tag_name new_tag_name | ADD BASE ON [db_name.]parent_stb_name [, [db_name.]parent_stb_name] ... | DROP BASE ON [db_name.]parent_stb_name [, [db_name.]parent_stb_name] ... } alter_table_options: alter_table_option ... alter_table_option: { COMMENT 'string_value' | KEEP value }

关键语义:修改超级表的 Schema 会影响其下所有子表;任何子表都不能单独修改自身 Schema(仅SET TAG更新标签值除外)。标签定义同样只能在超级表级别修改,并作用于该超级表下的全部子表。

禁止事项不能对超级表的主键列执行增、删、改操作(不能ADD COLUMN/DROP COLUMN/MODIFY COLUMN主键列)。

各操作说明:

操作说明
ADD COLUMN为超级表增加一个测点列
DROP COLUMN删除一个测点列,同时从所有子表中删除该列
MODIFY COLUMN仅可加长BINARYVARCHARNCHAR等变长类型测点列的长度;其他类型不可修改,长度不可缩短
ADD TAG增加一个标签列(总数 ≤128,总长度 ≤16 KB)
DROP TAG删除一个标签列,同时从所有子表中删除该标签
MODIFY TAG仅可加长BINARYVARCHARNCHAR等变长类型标签列的长度;其他类型不可修改,长度不可缩短
RENAME TAG重命名标签列,作用于所有子表
ADD BASE ON/DROP BASE ON修改虚拟超级表的继承关系,详见 Alter Inheritance

在解析器 sql.y 中可以看到:ALTER STABLE alter_table_clauseALTER TABLE共用同一套alter_table_clause文法,仅通过setAlterSuperTableType标记为超级表操作;ADD BASE ON/DROP BASE ON则对应createAlterTableBaseOn,这是超级表(确切说是虚拟超级表)独有的修改能力。

5.2 增加测点列

ALTER STABLE stb_name ADD COLUMN col_name column_type;

5.3 删除测点列

ALTER STABLE stb_name DROP COLUMN col_name;

5.4 修改测点列长度

ALTER STABLE stb_name MODIFY COLUMN col_name data_type(length);
  • 目标列必须是BINARYVARCHARNCHAR等变长类型;
  • 新长度必须大于现有长度,不允许缩短。

5.5 增加标签列

ALTER STABLE stb_name ADD TAG tag_name tag_type;

注意:增加后标签总数不能超过 128,所有标签总长度不能超过 16 KB。当向超级表新增标签列时,其下所有子表会自动继承新标签,新标签的默认值为NULL

5.6 删除标签列

ALTER STABLE stb_name DROP TAG tag_name;

5.7 重命名标签列

ALTER STABLE stb_name RENAME TAG old_tag_name new_tag_name;

5.8 修改标签列长度

ALTER STABLE stb_name MODIFY TAG tag_name data_type(length);
  • 目标标签必须是BINARYVARCHARNCHAR等变长类型;
  • 新长度必须大于现有长度,不允许缩短。

仓库测试 test_stable_alter_basic.py 覆盖了上述列/标签增删改的基础路径,可作为自行验证时的参照。

六、查询超级表

超级表支持使用SELECT进行投影与聚合查询,并可在WHERE子句中同时对测点列与标签列进行过滤。例如:

SELECT COUNT(*), AVG(voltage) FROM meters WHERE group_id = 2 AND ts >= NOW - 1h;

结果排序说明:如果超级表查询不包含ORDER BY,返回结果会按子表分组——先返回某个子表的全部记录,再返回下一个子表的全部记录,即返回数据整体不保证有序。如需严格排序,必须显式添加ORDER BY

SELECT * FROM meters WHERE ts >= NOW - 1h ORDER BY ts;

:::note 除"更新标签值"外,所有标签操作都只能在超级表上进行,不能对某个子表单独增加、删除或修改标签列。 :::

七、实战建议与注意事项

  1. 建模先行:把随设备变化的测点放列(Column),把相对静态的维度放标签(Tag),标签数尽量控制在 128 以内、总长度 16 KB 以内;超级表总列数(含标签)不要超过 4096。
  2. 利用复合主键:当同一时间戳下同一设备可能出现多条不同来源记录时,用COMPOSITE KEY声明第二主键,获得"时间戳 + 来源"维度的去重语义。
  3. 按需压缩:整数/浮点列可组合ENCODECOMPRESS降低存储成本;BINARY/NCHAR默认二级压缩为zstd,无需额外配置即可获得较好压缩率。
  4. KEEP 的生效时机:表级KEEP不会即时生效,必须FLUSH+COMPACT后才清除过期数据,且反复 compact + 改 KEEP 可能导致过期数据残留,生产环境应避免频繁调整。
  5. Schema 演进而非重建:需要新增测点/标签时优先使用ALTER STABLE ADD COLUMN / ADD TAG,一次性作用于全部子表;删除列/标签前确认该操作会级联到所有子表。
  6. 迁移复用:用SHOW CREATE STABLE导出的建表语句可直接在目标集群重放,保证结构完全一致。

八、总结

超级表是 TDengine 面向工业物联网(IIoT)场景的核心建模设施。本文以 Supertables 为主线,完整覆盖了CREATE STABLE(含复合主键、标签约束、SMA、KEEP、VIRTUAL、BASE ON)、SHOW/DESCRIBE系列查看命令、DROP STABLE的级联语义与空间释放机制、ALTER STABLE的列/标签/继承关系全量修改能力,以及超级表查询的排序行为。每一处关键限制都能在仓库源码中找到对应实现:列数上限定义在 tdef.h,标签上限定义在 tdef.h,创建校验逻辑位于 mndStb.c 的 mndCheckCreateStbReq,语法规则位于 sql.y。结合仓库中的测试用例(test_stable_keep_compact.py、test_stable_alter_basic.py),读者可以在本地环境直接复现并验证上述全部行为。

【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 23:48:41

开源免费、轻量高效的mdput:能否成为Typora的可靠平替

1. 为什么 Typora 用户都在找平替1.1 从 Typora 收费说起Typora 大概是 Markdown 编辑器里知名度最高的那个。它把“所见即所得”做到了极致——左边不用开预览窗口,输入#后面跟个空格,标题样式立刻呈现,打字体验几乎和 Word 一样流畅。2018 …

作者头像 李华
网站建设 2026/9/12 23:47:57

Bicep Code Review Results

Bicep Code Review Results 【免费下载链接】awesome-copilot Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot. 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot Compilatio…

作者头像 李华
网站建设 2026/9/12 23:47:49

go2rtc 日志分析实战指南:流媒体排查快速定位手册

go2rtc 日志分析实战指南:流媒体排查快速定位手册 【免费下载链接】go2rtc Ultimate camera streaming application 项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc 深夜摄像头画面突然卡死,切到 WebRTC 又黑屏几秒才恢复——如果你装…

作者头像 李华
网站建设 2026/9/12 23:43:52

无头服务器EGL display报错排查:从原理到软件渲染与Xvfb解决方案

1. 先把这个报错拆开看:到底是谁在喊救命如果你在无显示器的 Linux 服务器上部署过 OpenWebRX 这类 SDR 接收服务,大概率会对这行日志非常眼熟:Platform::WindowlessEglApplication::tryCreateContext(): cannot get default EGL display第一…

作者头像 李华
网站建设 2026/9/12 23:42:22

MATLAB实现无人机三维路径规划:双向A*算法与GUI设计

1. 项目背景与核心价值无人机三维路径规划是当前智能导航领域的热点研究方向,特别是在复杂环境下的自主飞行任务中显得尤为重要。传统二维规划方法无法满足无人机在真实三维空间中的导航需求,而基于双向A算法(Bi-A)的解决方案通过…

作者头像 李华