分类 :5.写入路径 | 篇章:01 SQL INSERT

适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-06-22
SQL INSERT 是 TDengine 最通用的写入方式。它支持单行/多行、单表/跨表、显式建表/隐式自动建表(USING 子句)等多种语法形式,是上层应用与 ETL 工具最常使用的入口。
核心概念速查表
| 概念 | 说明 |
|---|---|
| 单行插入 | 一条 SQL 一行数据 |
| 批量插入 | 一条 SQL 多行数据(VALUES 多组) |
| 跨表插入 | 一条 SQL 写入多张子表 |
| USING 子句 | 子表不存在时按超级表自动建表 |
| NOW | 写入时的服务端当前时间 |
| TS 主键 | 第一列必须是时间戳 |
详细解析
1. 基础语法
最简单的单行:
INSERT INTO d001 VALUES ('2026-06-04 12:00:00', 25.3, 220, 0.5);
省略时间用 NOW:
INSERT INTO d001 VALUES (NOW, 25.3, 220, 0.5);
显式指定列:
INSERT INTO d001 (ts, current) VALUES (NOW, 25.3);
-- 未指定列 → NULL
批量插入(强烈推荐):
INSERT INTO d001 VALUES
(NOW, 25.3, 220, 0.5),
(NOW+1s, 25.5, 221, 0.5),
(NOW+2s, 25.7, 220, 0.6);
2. 自动建表(USING)
USING 语法:
INSERT INTO d001
USING meters TAGS ('Beijing', 2)
VALUES (NOW, 25.3, 220, 0.5);
执行流程:
1. 检查子表 d001 是否存在
2. 不存在 → 按超级表 meters 创建子表
3. 设置 Tag (location='Beijing', groupid=2)
4. 写入数据
幂等性:
- 第二次执行:d001 已存在,跳过建表
- Tag 值会被忽略(不会更新)
批量自动建表:
INSERT INTO
d001 USING meters TAGS ('Beijing', 2) VALUES (NOW, 25.3, 220, 0.5),
d002 USING meters TAGS ('Shanghai', 3) VALUES (NOW, 26.1, 221, 0.6);
3. 跨表批量
跨表批量插入(最高效形式之一):
INSERT INTO
d001 VALUES (T1, 25.3, 220, 0.5), (T2, 25.5, 221, 0.5),
d002 VALUES (T1, 26.1, 221, 0.6), (T2, 26.3, 222, 0.6),
d003 VALUES (T1, 27.0, 220, 0.5);
执行行为:
- 一次 SQL 请求
- Parser 解析所有子表数据
- 按 VGroup 分组打包
- 并行下发到各 VNode
优势:
- 减少 SQL 解析次数
- 减少 RPC 往返
- 提升集群整体吞吐
4. 时间字面量与时区
时间字符串:
'2026-06-04 12:00:00.123' -- 毫秒精度
'2026-06-04T12:00:00+08:00' -- 带时区
'2026-06-04 12:00:00.123456' -- 微秒精度(库精度需匹配)
时间表达式:
NOW -- 当前服务端时间
NOW + 1h -- 当前 + 1 小时
TODAY() -- 今天 00:00:00
数字时间戳:
1717459200000 -- 毫秒精度的 Unix 时间戳
注意:
- 精度由数据库 PRECISION 决定(ms/us/ns)
- 字符串解析使用客户端时区
- 存储使用 UTC
5. NULL 与默认值
NULL 表示:
INSERT INTO d001 VALUES (NOW, NULL, 220, 0.5);
-- current 列为 NULL
省略列等价于 NULL:
INSERT INTO d001 (ts, voltage) VALUES (NOW, 220);
-- current 和 phase 都是 NULL
字符串 NULL 表达:
INSERT INTO d001 (ts, name) VALUES (NOW, NULL);
-- 区分 NULL 与空字符串 ''
6. 写入数据的合法性约束
写入约束:
① 时间戳唯一(同子表内):
- 默认:相同 ts 重复行被去重
- DUPLICATE_HANDLING=UPDATE 时:覆盖旧值
② 时间范围:
- 必须在数据库 KEEP 范围内
- 不能太老(超出 KEEP)
- 不能超未来过多(超出 DURATION 配置)
③ 数据类型匹配:
- 整数能写入浮点列
- 字符串能写入 NCHAR/VARCHAR(按长度截断/报错)
- 类型不匹配 → 报错
④ 子表必须存在或同时建表
7. 写入响应与重试
写入返回值:
- 成功:受影响行数(实际写入的行)
- 失败:错误码 + 错误消息
常见错误及处理:
- "Table does not exist" → 用 USING 自动建表
- "Timestamp out of range" → 检查 KEEP 配置
- "Network error" → 客户端重试
- "VGroup leader changed" → 客户端自动重定向到新 Leader
幂等性思考:
- 相同 ts + 数据 → 默认去重,安全重试
- DUPLICATE_HANDLING=UPDATE → 重试覆盖,需业务确认
8. 写入性能优化要点
批量大小建议:
- 单批 100~10000 行
- 太小 → RPC 开销大
- 太大 → 内存压力 + 单次失败影响大
跨表批量:
- 同 VGroup 的多子表组合最优
- 跨 VGroup 时引擎自动拆分
连接复用:
- 使用连接池
- 避免每次写入新建连接
异步写入(取决于连接器):
- 多线程并发提交
- 单连接串行处理避免锁竞争
代码示例
Python 示例
python
import taos
conn = taos.connect(host='localhost', user='root', password='taosdata', database='test')
# 批量插入
sql = """INSERT INTO d001 USING meters TAGS('Beijing', 2) VALUES
(NOW, 25.3, 220, 0.5),
(NOW+1s, 25.5, 221, 0.5),
(NOW+2s, 25.7, 220, 0.6)"""
affected = conn.execute(sql)
print(f"写入 {affected} 行")
跨表批量
sql
-- 一次 SQL 写入多个设备
INSERT INTO
d001 USING meters TAGS('BJ', 1) VALUES (NOW, 25.3, 220, 0.5),
d002 USING meters TAGS('SH', 2) VALUES (NOW, 26.1, 221, 0.6),
d003 USING meters TAGS('GZ', 3) VALUES (NOW, 27.0, 220, 0.5);
时间表达式
sql
-- 历史数据回填
INSERT INTO d001 VALUES
('2026-06-04 08:00:00', 24.0, 220, 0.5),
('2026-06-04 08:00:01', 24.1, 220, 0.5);
-- 相对时间
INSERT INTO d001 VALUES (NOW-1h, 25.0, 220, 0.5);
性能考量
批量大小影响
| 单批行数 | 吞吐(行/秒,单连接) | 备注 |
|---|---|---|
| 1 | ~5K | RPC 开销主导 |
| 100 | ~200K | 推荐起点 |
| 1000 | ~800K | 性价比最优 |
| 10000 | ~1M+ | 内存压力大 |
写入模式对比
| 模式 | 吞吐 | 适用场景 |
|---|---|---|
| 单行 INSERT | 低 | 极少量、临时数据 |
| 批量 INSERT | 中 | 通用 |
| 跨表批量 INSERT | 高 | 多设备汇总 |
| Schemaless | 高 | IoT 自动建模 |
| STMT 绑定 | 最高 | 大并发持续写入 |
FAQ
Q1: NOW 时间是客户端还是服务端?
服务端写入时获取的服务端时间。多客户端写入时建议显式指定 ts 避免时钟漂移。
Q2: 子表不存在能直接 INSERT 吗?
可以,但需要 USING 子句指定超级表和 Tag 值。否则会报"Table does not exist"错误。
Q3: 一条 SQL 最大能多大?
受配置 maxSQLLength 限制(默认 1MB)。跨表批量时按 VGroup 拆分后下发,单 VGroup 包不能超过 RPC 包大小限制。
Q4: 写入相同 ts 怎么处理?
默认去重(保留任一)。如需更新行为,建表时设置 DUPLICATE_HANDLING=UPDATE,或用 UPDATE 语句显式更新。
参考
系统构架篇
- 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 与查询优化》
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。