分类 :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 调用是原子的(要么全成功,要么全失败)。
参考
系统构架篇
- 01-《TDengine 整体架构全景》
- 02-《集群拓扑深度解析》
- 03-《MNode 内部机制深度解析》
- 04-《RPC 通信层深度解析》
- 05-《VNode 生命周期》
- 06-《RAFT 共识协议》
- 07-《端到端的消息流》
数据模型
- 01-《数据库创建与参数详解》
- 02-《超级表/子表/普通表》
- 03-《支持数据类型深度解析》
- 04-《TDengine Tag 设计哲学与 Schema 变更机制》
- 05-《TDengine 虚拟表实现原理》
存储引擎
- 01-《TDengine 存储引擎概览》
- 02-《TDengine MemTable 深度解析》
- 03-《TDengine WAL 预写日志机制》
- 04-《TDengine 数据文件格式》
- 05-《TDengine Commit 与 Flush 机制 》
- 06-《TDengine Compaction 合并策略 》
- 07-《TDengine 数据保留与 TTL》
- 08-《TDengine 压缩编码机制》
- 09-《TDengine Cache 与 Last 查询加速》
- 10-《TDengine 逻辑计划生成》
查询引擎
- 01-《TDengine 查询引擎概览》
- 02-《TDengine SQL 解析与词法分析》
- 03-《TDengine 语义分析与 AST 重写》
- 04-《TDengine 逻辑计划生成》
- 05-《TDengine 物理计划生成》
- 06-《TDengine 扫描算子》
- 07-《TDengine 聚合算子》
- 08-《TDengine 聚合算子》
- 09-《TDengine 连接算子》
- 10-《TDengine 排序、填充与投影》
- 11-《TDengine 分布式查询执行》
- 12-《TDengine EXPLAIN 与查询优化》