资讯详情

TDengine 数据建模实战:从数据库、超级表到虚拟表的一站式 SQL 建模指南

📅 2026/9/21 16:44:41 | 华诺云谱 👁 阅读
TDengine 数据建模实战:从数据库、超级表到虚拟表的一站式 SQL 建模指南
数据库时序数据库物联网大数据实时分析云原生【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址https://gitcode.com/taosdata/tdengine点击查看免费下载导读数据建模是 TDengine 时序数据库使用中最关键的第一步直接决定了写入性能、存储效率和查询灵活性。本文以智能电表为统一业务模型基于 基本概念 中定义的采集量、标签、超级表、子表、虚拟表等核心概念系统讲解使用 SQL 完成数据库、超级表、子表、普通表与虚拟表创建的完整流程从最基础的CREATE DATABASE参数调优到一个数据采集点一张表的建模范式再到支持先写入后建模的虚拟表高级分析能力。读完本文你将能够独立完成一套适合生产场景的 TDengine 数据模型设计与实现并理解每一步操作背后的存储与查询原理。数据建模前的基础理解四种对象与两种列在动手写 SQL 之前先明确 TDengine 数据模型中的核心角色详见 基本概念采集量随时间变化的物理量如电流current、电压voltage、相位phase构成表的普通列。标签附着在设备上的静态属性如位置location、分组group_id用于筛选与聚合。数据采集点产生数据的设备如d1001d1004四块智能电表TDengine 采取一个数据采集点一张表的设计策略。表 / 超级表 / 子表表存储单个采集点的数据超级表将同类型采集点聚合成逻辑整体子表是隶属于超级表的具体表。虚拟表不存储数据、基于真实表按时间戳对齐动态生成的逻辑表支持跨表跨库分析。由此引出本文要创建的完整对象链数据库库 → 超级表 → 子表 → 普通表 → 虚拟表。创建数据库存储策略的起点所有表都归属于某个数据库库而库的创建参数决定了数据的存储与淘汰策略。创建电表数据存储库的 SQL 如下CREATE DATABASE power PRECISION ms KEEP 3650 DURATION 10 BUFFER 16;该 SQL 创建名为power的数据库各参数含义PRECISION ms时间戳使用毫秒精度可选ms毫秒默认、us微秒、ns纳秒。KEEP 3650数据保留 3650 天超过该时长的数据将被自动删除以释放空间。取值[1, 365000]且必须大于等于DURATION的 3 倍。DURATION 10每 10 天的数据写入一个数据文件取值[60m, 3650d]支持m/h/d单位不带单位时按天计。BUFFER 16每个 vnode 写入内存池大小 16 MB默认为 256 MB取值[3, 16384]。需要说明的是BUFFER 16仅为教学演示的最小配置生产环境建议结合写入并发量合理增大。除上述参数外CREATE DATABASE还支持VGROUPS、REPLICA、PAGES、WAL_LEVEL等众多选项完整语法与取值范围可参考 数据库 DDL 参考。一个运行实例可包含多个库每个库可独立配置存储策略建议将数据特征采集频率、保留期限、副本数等不同的超级表放入不同的库中。创建完成后使用USE语句切换当前数据库后续插入、查询等操作默认在该库中进行USE power;创建超级表定义采集量与标签的模板超级表STable是 TDengine 解决表数量爆炸问题的关键抽象它将具有相同表结构的一类数据采集点聚合成一张逻辑表支持跨采集点的聚合查询。创建智能电表超级表meters的 SQL 如下CREATE STABLE meters ( ts timestamp, current float, voltage int, phase float ) TAGS ( location varchar(64), group_id int );语法要点CREATE STABLE是创建超级表的关键字meters为超级表名。表名后的括号中定义列第 1 列必须是时间戳列如ts timestamp。TDengine 以该列建立索引并采用列式存储从第 2 列开始是采集量列数据类型可为整型、浮点型、字符串等。TAGS关键字后的括号中定义标签标签数据类型可为整型、浮点型、字符串等标签名称不能与采集量列名相同标签是静态属性可随时通过ALTER STABLE增加、删除或修改修改对所有子表立即生效。从源码实现看创建表相关的 SQL 在 parser 模块 中完成语法树构建表类型、标签定义等选项均在此解析后下发执行。创建子表实例化数据采集点子表是隶属于某张超级表的具体表以超级表为模板、通过指定标签值创建。为设备d1001创建子表的 SQL 如下CREATE TABLE d1001 USING meters ( location, group_id ) TAGS ( California.SanFrancisco, 2 );其中USING表示使用meters超级表作为模板超级表名后的括号列出标签列名location、group_idTAGS后的括号给出子表的具体标签值位置为California.SanFrancisco分组 ID 为2。超级表自身不存储数据只充当模板数据全部存放在子表中。查询既可在子表上进行也可在超级表上进行——针对超级表的查询会先通过标签筛选出满足条件的子表再分别查询并合并结果。当对超级表进行写入或查询时可使用伪列tbname指定或输出对应子表的表名。自动建表写入即建表为简化数据接入TDengine 支持在写入时自动创建不存在的子表写入 SQL 中携带USING关键字与TAGS系统遇到不存在的子表时先自动建表再写入若子表已存在则直接写入无需额外步骤。示例INSERT INTO d1002 USING meters TAGS ( California.SanFrancisco, 2 ) VALUES ( NOW, 10.2, 219, 0.32 );这里NOW是 TDengine 内置的当前时间戳函数也可直接传入整型毫秒时间戳。自动建表机制让物联网设备数据无需预先建表即可接入是 TDengine 高写入吞吐的重要支撑。创建普通表无标签的独立表除子表外TDengine 还支持不带任何标签的普通表用法与传统关系型数据库表一致。创建普通表meter_n的 SQL 如下CREATE TABLE meter_n ( ts timestamp, current float, voltage int, phase float, location varchar(64), group_id int );普通表与子表的核心区别标签扩展性子表在普通表基础上增加了静态标签可携带更多元数据且标签支持增删改普通表没有标签。表归属子表总是隶属于某张超级表是超级表的一部分普通表独立存在不属于任何超级表。转换限制普通表无法转换为子表子表也无法转换为普通表表类型在创建时即确定。值得注意的是普通表模型意味着静态标签如location、group_id会重复存储在每一行数据中既增加存储开销也无法在查询时直接利用标签过滤性能通常低于超级表模型。因此除非业务确实不需要标签能力否则应优先采用超级表 子表的建模方式。多列模型与单列模型TDengine 支持两种数据模型设计多列模型推荐将同一数据采集点同时采集、时间戳一致的多个物理量作为不同列存储在同一张超级表中。写入与存储效率通常更优。单列模型每个物理量单独建立一张超级表。例如电流、电压、相位分别建 3 张超级表。适用于采集量种类频繁变化的场景——此时多列模型需要频繁修改超级表结构而单列模型可独立扩展每个物理量的表。两种模型并非互斥实际场景中可按需混用。创建虚拟表先写入后建模的跨表分析利器当采用单列模型或多个采集频率不同的传感器时很难用一张真实表完整描述一台设备跨表分析只能依赖多级关联查询易用性和性能都受影响。虚拟表VTable解决了这一问题虚拟表不存储数据查询时从一个或多个真实表按时间戳对齐、合并指定列动态生成结果让一个设备一张表的分析视角成为现实也使得先写入后建模成为可能——数据接入阶段无需预先设计复杂表结构存储后再按需定义虚拟表。虚拟表分三类虚拟普通表独立定义列与数据源、虚拟超级表模板定义公共列与标签、虚拟子表以虚拟超级表为模板创建。创建虚拟超级表时只需在CREATE STABLE中追加VIRTUAL 1选项默认VIRTUAL 0为普通超级表该选项的解析逻辑见 解析器实现 与 超级表 DDL 参考。虚拟表完整语法参见 虚拟表 DDL 参考。下面以智能电表为例演示虚拟表的两个典型场景。场景一单源多维度时序聚合单源指数据来自同一数据采集点但因单列建模被拆分成多张单列表。纵向拆分的数据可通过虚拟表还原为完整的横向状态。首先为电流、电压、相位分别创建 3 张单列超级表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四个设备分别创建上述 3 类超级表的子表CREATE TABLE current_d1001 USING current_stb (device_id, location, group_id) TAGS (d1001, California.SanFrancisco, 2); CREATE TABLE current_d1002 USING current_stb (device_id, location, group_id) TAGS (d1002, California.SanFrancisco, 3); CREATE TABLE current_d1003 USING current_stb (device_id, location, group_id) TAGS (d1003, California.LosAngeles, 3); CREATE TABLE current_d1004 USING current_stb (device_id, location, group_id) TAGS (d1004, California.LosAngeles, 2); CREATE TABLE voltage_d1001 USING voltage_stb (device_id, location, group_id) TAGS (d1001, California.SanFrancisco, 2); CREATE TABLE voltage_d1002 USING voltage_stb (device_id, location, group_id) TAGS (d1002, California.SanFrancisco, 3); CREATE TABLE voltage_d1003 USING voltage_stb (device_id, location, group_id) TAGS (d1003, California.LosAngeles, 3); CREATE TABLE voltage_d1004 USING voltage_stb (device_id, location, group_id) TAGS (d1004, California.LosAngeles, 2); CREATE TABLE phase_d1001 USING phase_stb (device_id, location, group_id) TAGS (d1001, California.SanFrancisco, 2); CREATE TABLE phase_d1002 USING phase_stb (device_id, location, group_id) TAGS (d1002, California.SanFrancisco, 3); CREATE TABLE phase_d1003 USING phase_stb (device_id, location, group_id) TAGS (d1003, California.LosAngeles, 3); CREATE TABLE phase_d1004 USING phase_stb (device_id, location, group_id) TAGS (d1004, California.LosAngeles, 2);创建虚拟超级表meters_v将 3 种采集量聚合为一张逻辑表CREATE STABLE meters_v ( ts timestamp, current float, voltage int, phase float ) TAGS ( location varchar(64), group_id int ) VIRTUAL 1;再为 4 个设备分别创建虚拟子表通过列名 FROM 源表.源列语法引用数据源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为例其电流、电压、相位 3 张源表的原始数据如下时间戳单位为毫秒current_d1001voltage_d1001phase_d1001TimestampCurrentTimestampVoltageTimestampPhase153854868500010.3153854868500021915385486850000.31153854869500012.6153854869500021815385486950000.33153854869680012.3153854869680022115385486968000.31153854869710012.1153854869710022015385486972000.32153854869770011.8153854869780022215385486978000.33写入上述数据的 SQL一条多表插入语句各源表按表名 VALUES ...分组INSERT INTO current_d1001 VALUES (1538548685000, 10.3), (1538548695000, 12.6), (1538548696800, 12.3), (1538548697100, 12.1), (1538548697700, 11.8) voltage_d1001 VALUES (1538548685000, 219), (1538548695000, 218), (1538548696800, 221), (1538548697100, 220), (1538548697800, 222) phase_d1001 VALUES (1538548685000, 0.31), (1538548695000, 0.33), (1538548696800, 0.31), (1538548697200, 0.32), (1538548697800, 0.33);查询虚拟表d1001_vSELECT * FROM d1001_v;结果如下虚拟表以时间戳对齐各源列某源表无数据的时间点对应列填充NULLtscurrentvoltagephase153854868500010.32190.31153854869500012.62180.33153854869680012.32210.31153854869710012.1220NULL1538548697200NULLNULL0.32153854869770011.8NULLNULL1538548697800NULL2220.33从结果可以看到虚拟表的列合并完全以时间戳为基准多表在同一时间戳有数据则组合成一行仅部分表有数据则其余列填NULL这正是时间戳对齐语义的直观体现。场景二跨源采集量对比分析跨源指数据来自不同数据采集点。可以从不同设备提取语义可比的采集量通过虚拟表按时间戳对齐合并后进行对比分析。以对比d1001d1004四个设备的电流为例创建虚拟普通表current_v注意此处未使用USING属于独立定义的虚拟普通表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 );4 个设备的电流源数据如下current_d1001current_d1002current_d1003current_d1004TimestampCurrentTimestampCurrentTimestampCurrentTimestampCurrent153854868500010.3153854868500011.7153854868500011.2153854868500012.4153854869500012.6153854869500011.9153854869500010.8153854869500011.3153854869680012.3153854869680012.4153854869680012.3153854869680010.1153854869710012.1153854869720012.2153854869710011.1153854869720011.7153854869770011.8153854869770011.4153854869780012.1153854869780012.6写入数据的 SQLINSERT INTO current_d1001 VALUES (1538548685000, 10.3), (1538548695000, 12.6), (1538548696800, 12.3), (1538548697100, 12.1), (1538548697700, 11.8) current_d1002 VALUES (1538548685000, 11.7), (1538548695000, 11.9), (1538548696800, 12.4), (1538548697200, 12.2), (1538548697700, 11.4) current_d1003 VALUES (1538548685000, 11.2), (1538548695000, 10.8), (1538548696800, 12.3), (1538548697100, 11.1), (1538548697800, 12.1) current_d1004 VALUES (1538548685000, 12.4), (1538548695000, 11.3), (1538548696800, 10.1), (1538548697200, 11.7), (1538548697800, 12.6);查询虚拟表current_vSELECT * FROM current_v;结果如下tsd1001_currentd1002_currentd1003_currentd1004_current153854868500010.311.711.212.4153854869500012.611.910.811.3153854869680012.312.412.310.1153854869710012.1NULL11.1NULL1538548697200NULL12.2NULL11.7153854869770011.811.4NULLNULL1538548697800NULLNULL12.112.6虚拟表的使用约束与进阶能力使用虚拟表时需注意以下几点详见 虚拟表 DDL 参考只读虚拟表不能写入或删除数据只能查询其数据在每次查询时动态生成只有查询中引用的列才会被合并因此同一虚拟表在不同查询中呈现的数据可能不同。列引用语法CREATE VTABLE中FROM关键字前的名称为虚拟表侧列名FROM后为数据源侧名称支持[db_name.]table_name.col_name跨库跨表指定数据源。标签虚拟子表的标签值可以是常量也可以通过FROM [db_name.]table_name.tag_name引用源表的标签tag-ref。批量创建一条CREATE VTABLE语句可包含多个虚拟子表建表子句子句间不用逗号分隔便于批量建模。继承虚拟超级表支持BASE ON继承其他虚拟超级表的列和标签。来源灵活虚拟表的数据源可以是子表、普通表甚至已有虚拟表且无论源数据分布在一个库还是多个库都能跨库跨表聚合。建模建议小结优先使用超级表 子表模型将静态属性建模为标签而非重复列兼顾存储效率与标签过滤能力普通表仅在无标签需求的场景使用。库级参数按业务数据特征配置时间戳精度、保留时长KEEP、文件跨度DURATION、内存池BUFFER等需与采集频率和留存策略匹配建议参考 数据库 DDL 参考 按需调优。充分利用自动建表数据接入阶段使用INSERT ... USING ... TAGS免去预建表步骤。单列模型配合虚拟表实现先写入后建模当采集量种类多变或采集频率不一致时先用最贴近设备协议的方式写入再通过虚拟表虚拟超级表 / 虚拟子表 / 虚拟普通表按业务视角动态建模实现一个设备一张表的分析体验。完成建模后可继续阅读 写入数据 与 查询与聚合掌握在本文所建模型上的实际读写与聚合操作。赞分享数据库时序数据库物联网大数据实时分析云原生【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址https://gitcode.com/taosdata/tdengine点击查看免费下载相关推荐TDengine 数据建模实战从数据库、超级表到虚拟表的完整建模指南TDengine 数据建模实战从数据库、超级表到虚拟表的完整建模指南 TDengine 采用一个数据采集点一张表 超级表聚合 虚拟表分析的三层数据数据库时序数据库大数据物联网云原生TDengine 数据建模实战用 SQL 创建数据库、超级表、子表与虚拟表TDengine 数据建模实战用 SQL 创建数据库、超级表、子表与虚拟表 本文基于 TDengine 官方快速入门中的 Data Modeling 章节以数据库时序数据库物联网大数据实时分析云原生TDengine 数据建模实战指南数据库、超级表、子表与虚拟表的设计与 SQL 实现TDengine 数据建模实战指南数据库、超级表、子表与虚拟表的设计与 SQL 实现 TDengine 面向工业物联网IIoT场景以一表一采集点为核数据库时序数据库大数据物联网云原生上一篇从学术到工业级应用Qwen3-ForcedAligner-0.6B-hf的性能基准与最佳实践下一篇终极指南如何让老款Mac免费升级到最新macOS系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。