TDengine Schemaless 写入 — InfluxDB Line、OpenTSDB JSON/Telnet 协议

分类 :5.写入路径 | 篇章:02 Schemaless 写入

适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-06-23

Schemaless 写入让设备无需预先建表即可直接上报数据,TDengine 根据数据自动推断超级表 Schema、创建子表。它原生兼容 InfluxDB Line Protocol、OpenTSDB Telnet/JSON 三种协议,是 IoT 数据快速接入的首选方式。

核心概念速查表

概念 说明
Schemaless 无需预定义 Schema 的写入
InfluxDB Line 文本协议,measurement,tag=v field=v ts
OpenTSDB Telnet 文本协议,put metric ts value tag=v
OpenTSDB JSON JSON 格式批量上报
Measurement 度量名(→ 超级表名)
Tag Set 标签集(→ Tag 列)
Field Set 字段集(→ 数据列)

详细解析

1. InfluxDB Line Protocol

复制代码
基本格式:
  <measurement>,<tag-key>=<tag-value>,... <field-key>=<field-value>,... <timestamp>

示例:
  meters,location=Beijing,groupid=2 current=25.3,voltage=220,phase=0.5 1717459200000

  解析为:
    超级表:meters
    Tag:location='Beijing', groupid=2
    Field:current=25.3, voltage=220, phase=0.5
    时间:1717459200000(毫秒)


多行批量:
  meters,location=Beijing current=25.3 1717459200000
  meters,location=Beijing current=25.5 1717459201000
  meters,location=Shanghai current=26.0 1717459200000


类型推断:
  25.3       → DOUBLE
  25.3i      → BIGINT
  25.3f      → FLOAT
  "text"     → NCHAR
  t / true   → BOOL
  L"unicode" → NCHAR

2. OpenTSDB Telnet

复制代码
基本格式:
  put <metric> <timestamp> <value> <tag-key>=<tag-value>...

示例:
  put meters_current 1717459200 25.3 location=Beijing groupid=2
  
  解析为:
    超级表:meters_current(每个 metric 一个超级表)
    Tag:location='Beijing', groupid=2
    Field:value=25.3
    时间:1717459200(秒)

  特点:
    - 一行一个 metric
    - value 列固定名 "value"
    - 多 metric 需要多行

3. OpenTSDB JSON

json 复制代码
{
  "metric": "meters_current",
  "timestamp": 1717459200000,
  "value": 25.3,
  "tags": {
    "location": "Beijing",
    "groupid": "2"
  }
}
复制代码
批量数组:
  [
    {"metric": "m1", "timestamp": T1, "value": 1.0, "tags": {...}},
    {"metric": "m2", "timestamp": T2, "value": 2.0, "tags": {...}}
  ]


特点:
  - 结构化(易构造)
  - 自动从 timestamp 长度推断精度
  - 支持嵌套 tags

4. 自动建表流程

复制代码
Schemaless 第一次接收新设备数据:

  ① 解析协议提取:measurement, tag set, field set, timestamp
  ② 计算子表名(基于 measurement + tags 哈希)
  ③ 检查超级表是否存在
     - 不存在 → 创建超级表(用当前数据推断 Schema)
     - 存在 → 检查 Schema 兼容性
  ④ 检查子表是否存在
     - 不存在 → 创建子表(用 tag 值)
     - 存在 → 直接写入
  ⑤ 写入数据


子表名生成规则:
  - 由 (super_table + tags) 哈希得出
  - 同一 tag 组合永远生成相同子表名
  - 名字以 't_' 前缀 + 哈希值


Schema 演化:
  - 新字段 → 自动 ADD COLUMN
  - 类型变化 → 取更宽类型(INT → BIGINT)
  - Tag 新增 → 自动 ADD TAG

5. 写入 API 模式

复制代码
连接器 API:

  taos_schemaless_insert(
    conn,
    lines,       // 数据行(字符串数组)
    numLines,    // 行数
    protocol,    // INFLUXDB / OPENTSDB_TELNET / OPENTSDB_JSON
    precision    // 时间精度
  )

  返回:受影响行数 或 错误码


扩展 API(指定数据库/精度/TTL):

  taos_schemaless_insert_with_reqid(...)
    - 带请求 ID,便于追踪
    
  taos_schemaless_insert_ttl(...)
    - 子表带 TTL


REST API:
  POST /influxdb/v1/write?db=test&precision=ms
    body: <line-protocol 数据>


taosAdapter HTTP 端口:
  - InfluxDB 兼容:/influxdb/v1/write
  - OpenTSDB Telnet:TCP 端口
  - OpenTSDB HTTP:/opentsdb/v1/put

6. 协议对比

协议 格式 优势 劣势
InfluxDB Line 紧凑文本 单行多 Field 转义复杂
OpenTSDB Telnet 文本 简单易懂 单 Field
OpenTSDB JSON 结构化 易构造、扩展性强 体积大

7. 数据上报场景

复制代码
设备直连(推荐):
  设备 → MQTT/HTTP → taosAdapter → TDengine
  
边缘网关聚合:
  设备 → 网关 → 批量 Line Protocol → taosAdapter
  
现有 InfluxDB/OpenTSDB 迁移:
  原有上报代码不变,目标端切到 taosAdapter
  
Telegraf / collectd 等采集器:
  原生支持 InfluxDB Line 输出
  改 endpoint 即可对接 TDengine

8. Schemaless 的限制

复制代码
限制:
  - Tag 数量上限(默认 128 个)
  - Tag 值长度限制(默认 16384)
  - 单行 Field 数量上限
  - 子表数量上限(数据库配置)
  - 类型推断后不能轻易降级

最佳实践:
  - 同一 measurement 字段类型保持一致
  - Tag 设计避免高基数(如 user_id 不适合做 Tag)
  - 时间精度统一(避免不同精度混用)

代码示例

Python InfluxDB Line

python 复制代码
import taos

conn = taos.connect(host='localhost', user='root', password='taosdata', database='test')
lines = [
    "meters,location=Beijing,groupid=2 current=25.3,voltage=220i 1717459200000",
    "meters,location=Shanghai,groupid=3 current=26.1,voltage=221i 1717459200000",
]
conn.schemaless_insert(
    lines=lines,
    protocol=taos.SmlProtocol.LINE_PROTOCOL,
    precision=taos.SmlPrecision.MILLI_SECONDS
)

REST API

bash 复制代码
curl -u root:taosdata -X POST \
  "http://localhost:6041/influxdb/v1/write?db=test&precision=ms" \
  -d "meters,location=Beijing current=25.3,voltage=220i 1717459200000"

Telegraf 配置示例

toml 复制代码
[[outputs.influxdb]]
  urls = ["http://localhost:6041/influxdb/v1"]
  database = "telegraf"
  username = "root"
  password = "taosdata"

性能考量

性能对比

写入方式 单连接吞吐 建表开销
首次 Schemaless 高(自动建表)
持续 Schemaless 几乎为零(缓存命中)
普通 SQL 需预建表
STMT 参数绑定 最高 需预建表

优化建议

  • 同一批次内尽量按 measurement 分组
  • 单批 100~1000 行
  • 复用连接(连接池)
  • taosAdapter 多实例横向扩展

FAQ

Q1: 自动建表后如何修改 Schema?

可以用 ALTER STABLE 显式修改。Schemaless 后续写入会按新 Schema 处理。

Q2: Tag 设计错误如何修复?

需手动 ALTER STABLE 修改 Tag 结构。建议初次设计前充分评估高/低基数 Tag。

Q3: 同一 measurement 在不同行字段不一致?

TDengine 会取并集作为 Schema。缺失字段按 NULL 处理。建议字段集稳定。

Q4: Schemaless 写入支持事务吗?

不支持显式事务,但单次 API 调用是原子的(要么全成功,要么全失败)。

参考

系统构架篇

数据模型

存储引擎

查询引擎

数据写入