TDengine Schemaless 无模式写入指南:行协议、自动建表规则与多语言实战 📅 发布时间:2026/9/13 14:49:39 👁 浏览次数: TDengine Schemaless 无模式写入指南行协议、自动建表规则与多语言实战【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine导读在工业物联网IIoT场景中设备采集项往往随应用逻辑升级、硬件调整而频繁变化若每次都手工建表将极大拖慢数据接入节奏。TDengine 提供了 Schemaless无模式写入方式无需预先创建超级表与子表写入时自动完成建表、加列与类型推断同时保持与 InfluxDB Line Protocol、OpenTSDB Telnet / JSON 协议的兼容。本文基于 TDengine 开源仓库的开发者指南文档docs/en/10-developer-guide/04-schemaless.md与对应源码、示例系统讲解行协议语法、自动建表命名规则、配置项、时间精度识别、数据模式映射与变化处理并给出 WebSocket 与 Native 两种连接的 Java/Python/Go/Rust/Node.js/C#/C 多语言可运行示例帮助你快速上手并规避常见写入错误。Schemaless 写入机制概述在 IoT 应用中为达成自动化管理、业务分析、设备监控等功能往往需要采集大量数据项。由于应用逻辑升级、设备硬件调整等原因采集项可能频繁变化。TDengine 的 Schemaless 写入方法正是为简化数据记录流程而设计。其核心机制包含三点自动建表用户无需预先创建超级表supertable或子表subtableTDengine 会根据实际写入的数据自动创建对应的存储结构。自动加列必要时自动为已存在的表补充缺失的数据列普通列或标签列tag确保用户写入的数据被正确存储。与 SQL 建表等价通过 Schemaless 写入创建的超级表及其子表与直接通过 SQL 创建的表在功能上没有任何差异仍可直接使用 SQL 写入数据。唯一的区别在于由 Schemaless 自动生成的子表名基于标签值按固定映射规则生成可读性较差、不易直接理解。重要提示使用 Schemaless 写入时表由系统自动创建手动创建同名表可能导致未知错误同理文档也不推荐手动预建超级表否则数据插入可能异常。Schemaless 写入行协议TDengine 的 Schemaless 行协议兼容三类协议InfluxDB 行协议Line ProtocolOpenTSDB Telnet 行协议OpenTSDB JSON 格式协议其中 InfluxDB 与 OpenTSDB 的标准协议写法请参考其各自官方文档。下面重点介绍 TDengine 在 InfluxDB 行协议基础上扩展出的协议内容它允许用户更精细地控制超级表 schema。每一行数据用一条字符串表达多条行字符串可一次性传入写入 API 实现批量写入格式为measurement,tag_set field_set timestamp各组成部分说明如下组成部分格式说明measurement表名与tag_set之间用逗号分隔tag_settag_keytag_value,tag_keytag_value标签列数据各项用逗号分隔与field_set之间用空格分隔field_setfield_keyfield_value,field_keyfield_value普通列数据各项用逗号分隔与timestamp之间用空格分隔timestamp时间戳该行数据的主键时间戳注意Schemaless 写入不支持向带第二复合主键列的表写入数据。tag_set中的所有数据都会被自动转换为nchar数据类型无需使用双引号。数据项类型标注field_set 类型描述在 Schemaless 行协议中field_set中的每个数据项都需要描述自身的数据类型规则如下写法类型示例双引号包裹varcharBinaryabc双引号包裹且前缀L或lncharL error message 双引号包裹且前缀G或ggeometryGPoint(4.343 89.342)双引号包裹且前缀B或bvarbinaryB\x98f46e、Bhello双引号内可含以\x开头的十六进制也可为普通字符串转义规则对于空格、等号、逗号,、双引号、反斜杠\都需要使用反斜杠进行转义全部为半角英文符号。各字段域domain的转义规则如下编号字段需转义的字符1超级表名逗号、空格2标签名逗号、等号、空格3标签值逗号、等号、空格4列名逗号、等号、空格5列值双引号、反斜杠反斜杠自身的转义遵循连续反斜杠规则若连续出现两个反斜杠第一个作为转义字符若只有一个反斜杠则无需转义。具体映射如下编号反斜杠原始转义结果1\\2\\\3\\\\\4\\\\\\5\\\\\五个\\\\6\\\\\\六个\\\\数值类型后缀映射数值类型通过后缀区分映射规则如下编号后缀映射类型字节数1无后缀或f64double82f32float43i8/u8TinyInt / UTinyInt14i16/u16SmallInt / USmallInt25i32/u32Int / UInt46i64/i/u64/uBigInt / BigInt / UBigInt / UBigInt8此外t、T、true、True、TRUE、f、F、false、False会被直接识别为BOOL类型。完整示例下面这行数据表示在名为st的超级表下以标签t13NCHAR、t24NCHAR、t3t3NCHAR定位子表写入一行数据列c13BIGINT、c2falseBOOL、c3passitBINARY、c44DOUBLE主键时间戳为1626006833639000000st,t13,t24,t3t3 c13i64,c3passit,c2false,c44f64 1626006833639000000注意如果数据类型后缀描述有误如大小写错误或为数据指定的类型本身不正确可能触发错误信息并导致写入失败。幂等性与原子性TDengine 为数据写入提供了幂等性可以重复调用 API 写入之前写入失败的数据不会产生重复副作用。但不提供多行数据的原子性批量写入多行数据时可能出现部分行成功、部分行失败的情况需要应用侧根据返回错误码做补偿处理。Schemaless 写入处理规则Schemaless 写入按以下 12 条原则处理行数据子表名生成规则先将 measurement 名称与标签的 key、value 拼接为如下字符串measurement,tag_key1tag_value1,tag_key2tag_value2注意tag_key1、tag_key2并非用户输入时的原始顺序而是按标签名升序排序后的结果因此tag_key1不一定是行协议中第一个输入的标签。排序后对该字符串计算 MD5 哈希值md5_val再将计算结果与字符串拼接生成表名t_md5_val。t_是固定前缀所有通过该映射自动生成的表都带此前缀。如果不想使用自动生成的表名有两种方式指定子表名方式一优先级更高在taos.cfg中配置smlAutoChildTableNameDelimiter取值不能包含 # 空格 CR LF 制表符。例如配置smlAutoChildTableNameDelimiter-后写入st,t0cpu1,t14 c13 1626006833639000000创建的表名为cpu1-4。在taos.cfg中配置smlChildTableName。例如配置smlChildTableNametname后写入st,tnamecpu1,t14 c13 1626006833639000000创建的表名为cpu1。注意如果多行数据具有相同的tname但tag_set不同则以首次自动建表时指定的 tag_set 为准其余行会被忽略。若解析行协议得到的超级表不存在则自动创建不推荐手动创建超级表否则数据插入可能异常。若解析得到的子表不存在则按第 1 步确定的子表名创建子表。若数据行中指定的标签列或普通列不存在会将其添加到超级表中只增不减。若超级表中已存在某些标签列或普通列但某数据行未指定它们则该行中这些列的值为NULL。对于 BINARY 或 NCHAR 列若数据行提供的值长度超过列类型上限会自动扩大该列的最大字符存储上限只增不减确保数据完整存储。整个处理过程中遇到的错误会中断写入流程并返回错误码。为提高写入效率默认假设同一超级表内field_set的列顺序一致首条数据包含全部字段后续数据沿用该顺序。若顺序不同需配置smlDataFormat为false否则数据会按相同顺序写入导致库内数据错乱。自3.0.3.0版本起系统会自动检查顺序一致性该配置已废弃。由于 SQL 建表不支持点号.Schemaless 会将自动创建的表名中的点号替换为下划线_。若手工指定子表名且包含点号也会被转换为下划线。taos.cfg新增smlTsDefaultName配置值为字符串仅作用于客户端。配置后可通过它设置 Schemaless 自动建表的时间列名未配置时默认为_ts。Schemaless 写入中的超级表名、子表名区分大小写。Schemaless 写入仍受 TDengine 底层数据结构限制每行数据总长度不能超过 48KB自3.0.5.0版本起为 64KB标签值总长度不能超过 16KB。配置项在源码中的注册位置上述smlChildTableName、smlAutoChildTableNameDelimiter、smlTagName、smlTsDefaultName、smlDot2Underline等配置项均作为客户端本地CFG_SCOPE_CLIENT / CFG_CATEGORY_LOCAL动态配置在 source/common/src/tglobal.c 中注册且支持运行时动态调整CFG_DYN_CLIENT可在taos.cfg中集中管理也可以在连接建立前通过客户端 API 设置。时间分辨率识别Schemaless 写入支持三种指定模式编号值描述1SML_LINE_PROTOCOLInfluxDB Line Protocol2SML_TELNET_PROTOCOLOpenTSDB Text Line Protocol3SML_JSON_PROTOCOLJSON 格式协议在SML_LINE_PROTOCOL解析模式下用户需要显式指定输入时间戳的时间分辨率可选值如下编号时间分辨率定义含义1TSDB_SML_TIMESTAMP_NOT_CONFIGURED未定义非法2TSDB_SML_TIMESTAMP_HOURS小时3TSDB_SML_TIMESTAMP_MINUTES分钟4TSDB_SML_TIMESTAMP_SECONDS秒5TSDB_SML_TIMESTAMP_MILLI_SECONDS毫秒6TSDB_SML_TIMESTAMP_MICRO_SECONDS微秒7TSDB_SML_TIMESTAMP_NANO_SECONDS纳秒在SML_TELNET_PROTOCOL与SML_JSON_PROTOCOL模式下时间精度由时间戳的长度决定与 OpenTSDB 标准行为一致用户指定的时间分辨率将被忽略。数据模式映射规则InfluxDB 行协议数据会被映射为带 schema 的表结构映射关系为measurement→ 超级表名tag_set中的标签名 → schema 中的标签名field_set中的字段名 → 普通列名以如下数据为例st,t13,t24,t3t3 c13i64,c3passit,c2false,c44f64 1626006833639000000该行数据映射创建超级表st包含 3 个 nchar 类型标签t1、t2、t3以及 5 个数据列tstimestamp、c1bigint、c3binary、c2bool、c4bigint等价于如下 SQLcreate stable st (_ts timestamp, c1 bigint, c2 bool, c3 binary(6), c4 bigint) tags(t1 nchar(1), t2 nchar(1), t3 nchar(2))可见数值后缀直接决定列类型如3i64映射为 bigint双引号字符串按长度映射为binary(n)标签值按长度映射为nchar(n)。数据模式变化处理本节说明不同行数据写入场景对数据 schema 的影响。场景一显式类型标识变更 → 报错使用行协议写入带明确类型标识的字段时后续若改变该字段的类型定义将触发明确的数据 schema 错误写入 API 返回错误。例如st,t13,t24,t3t3 c13i64,c3passit,c2false,c44 1626006833639000000 st,t13,t24,t3t3 c13i64,c3passit,c2false,c44i 1626006833640000000第一行将c4定义为 Double第二行却通过数值后缀将同一列声明为 BigInt从而触发 Schemaless 解析错误。场景二BINARY 列长度扩展 → 自动加宽若前面行将某数据列声明为 binary后续行需要更长的二进制长度将触发超级表 schema 变更自动加宽st,t13,t24,t3t3 c13i64,c5pass 1626006833639000000 st,t13,t24,t3t3 c13i64,c5passit 1626006833640000000第一行声明列c5为binary(4)第二行写入时识别到c5仍为 binary 列但宽度为 6此时自动将列宽扩大以容纳新字符串binary(6)。场景三新增列 → 自动加列st,t13,t24,t3t3 c13i64 1626006833639000000 st,t13,t24,t3t3 c13i64,c6passit 1626006833640000000第二行相对第一行新增了列c6类型为binary(6)系统将自动为超级表添加c6binary(6)列。Schemaless 写入示例智能电表场景下面以智能电表为例介绍使用各类语言连接器通过 Schemaless 写入接口写数据的代码示例覆盖 InfluxDB Line Protocol、OpenTSDB Telnet 与 OpenTSDB JSON 三种协议。运行前提由于 Schemaless 自动建表规则与 SQL 示例不同运行前请确保meters、metric_telnet、metric_json等表不存在。OpenTSDB Telnet 行协议与 OpenTSDB JSON 格式协议仅支持一个数据列因此示例采用了其他数据组合。WebSocket 连接方式WebSocket 连接通过 REST/WebSocket 网关默认端口 6041写入典型示例文件如下Java执行带reqId的 Schemaless 写入最后一个参数reqId可用于请求链路追踪writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS, 1L);完整代码参见 docs/examples/JDBC/JDBCDemo/src/main/java/com/taos/example/SchemalessWsTest.java。Pythondocs/examples/python/schemaless_ws.py先创建数据库power再通过conn.schemaless_insert(...)分别以 Line、Telnet、Json 三种协议写入import taosws host localhost port 6041 lineDemo [ meters,groupid2,locationCalifornia.SanFrancisco current10.3000002f64,voltage219i32,phase0.31f64 1626006833639 ] telnetDemo [metric_telnet 1707095283260 4 hosthost0 interfaceeth0] jsonDemo [ {metric: metric_json,timestamp: 1626846400,value: 10.3, tags: {groupid: 2, location: California.SanFrancisco, id: d1001}} ] conn taosws.connect(userroot, passwordtaosdata, hosthost, portport, databasepower) conn.schemaless_insert( lineslineDemo, protocoltaosws.PySchemalessProtocol.Line, precisiontaosws.PySchemalessPrecision.Millisecond, ttl1, req_id1, ) conn.schemaless_insert( linestelnetDemo, protocoltaosws.PySchemalessProtocol.Telnet, precisiontaosws.PySchemalessPrecision.Microsecond, ttl1, req_id2, ) conn.schemaless_insert( linesjsonDemo, protocoltaosws.PySchemalessProtocol.Json, precisiontaosws.PySchemalessPrecision.Millisecond, ttl1, req_id3, )可以看到WebSocket 版 API 还支持ttl数据生命周期与req_id链路追踪参数。Go推荐使用ws/unifiedSchemaless 接口自v3.8.0起见 docs/examples/go/schemaless/unified/main.gows/schemaless兼容接口docs/examples/go/schemaless/ws/main.go自v3.8.0起标记为废弃暂时仍可用建议迁移。Rustdocs/examples/rust/restexample/examples/schemaless.rs、Node.jsdocs/examples/node/websocketexample/line_example.js、C#docs/examples/csharp/wssml/Program.cs、Cdocs/examples/c-ws-new/sml_insert_demo.c均有对应示例。REST API不支持Schemaless 写入。Native 连接方式Native 连接使用 TCP 原生协议默认端口 6030示例文件如下Java同样支持带reqId的写入参见 docs/examples/JDBC/JDBCDemo/src/main/java/com/taos/example/SchemalessJniTest.java。Pythondocs/examples/python/schemaless_native.pyimport taos lineDemo [ meters,groupid2,locationCalifornia.SanFrancisco current10.3000002f64,voltage219i32,phase0.31f64 1626006833639 ] telnetDemo [metric_telnet 1707095283260 4 hosthost0 interfaceeth0] jsonDemo [ {metric: metric_json,timestamp: 1626846400,value: 10.3, tags: {groupid: 2, location: California.SanFrancisco, id: d1001}} ] conn taos.connect(userroot, passwordtaosdata, hostlocalhost, port6030) conn.execute(CREATE DATABASE IF NOT EXISTS power) conn.select_db(power) conn.schemaless_insert( lineDemo, taos.SmlProtocol.LINE_PROTOCOL, taos.SmlPrecision.MILLI_SECONDS ) conn.schemaless_insert( telnetDemo, taos.SmlProtocol.TELNET_PROTOCOL, taos.SmlPrecision.MICRO_SECONDS ) conn.schemaless_insert( jsonDemo, taos.SmlProtocol.JSON_PROTOCOL, taos.SmlPrecision.MILLI_SECONDS )Native 版通过taos.SmlProtocol.LINE_PROTOCOL / TELNET_PROTOCOL / JSON_PROTOCOL与taos.SmlPrecision.*指定协议与时间精度。Godocs/examples/go/schemaless/native/main.go、Rustdocs/examples/rust/nativeexample/examples/schemaless.rs、C#docs/examples/csharp/nativesml/Program.cs、Cdocs/examples/c/schemaless.c均有对应示例。Node.js 与 REST API不支持Native Schemaless 写入。查询写入的数据运行上述示例后power数据库中会自动创建相应表。可使用 TDengine CLI 或应用程序查询验证写入结果例如taos show power.stables; stable_name | meter_current | stb0_0 | meters | Query OK, 3 row(s) in set (0.002527s) taos select * from power.meters limit 1 \G; *************************** 1.row *************************** _ts: 2021-07-11 20:33:53.639 current: 10.300000199999999 voltage: 219 phase: 0.310000000000000 groupid: 2 location: California.SanFrancisco Query OK, 1 row(s) in set (0.004501s)可以看到meters超级表已按智能电表场景自动建表标签groupid、location与普通列current、voltage、phase均被正确存储时间列默认为_ts。你既可以用 CLI 交互查询也可以在应用中通过 SQL 直接读写这些自动创建的表。实践建议与注意事项综合文档与源码使用 Schemaless 写入时建议遵循以下实践不要手动预建表让系统自动建表避免与自动命名规则冲突引发未知错误。保持同一超级表内 field_set 顺序一致虽然 3.0.3.0 之后系统会自动校验列顺序但保持一致的字段顺序仍是提升解析与写入效率的好习惯。正确选择时间精度Line 协议必须显式指定时间分辨率毫秒/微秒/纳秒等Telnet 与 JSON 协议按时间戳长度推断精度注意与写入数据匹配。善用子表名定制若自动生成的t_md5表名不利于后续 SQL 检索可通过smlAutoChildTableNameDelimiter或smlChildTableName两个客户端配置指定可读的子表名。留意底层限制单行数据总长度不超过 64KB3.0.5.0 起标签值总长度不超过 16KBBINARY/NCHAR 列超长时会自动加宽只增不减但列类型冲突如 Double 变 BigInt会直接报错。充分利用幂等性写入失败后可重复调用 API 重试但多行批量写入不具备原子性需按返回错误码做局部补偿。通过本文的协议语法、自动建表规则与多语言示例你可以将任意 IIoT 设备的动态采集项以最小改造成本接入 TDengine并依靠 SQL 继续完成后续的查询、订阅与流式计算。【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考