TDengine SQL INSERT — 单行、批量、跨表与子表自动建表

分类: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 示例

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 写入多个设备
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);

时间表达式

-- 历史数据回填
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~5KRPC 开销主导
100~200K推荐起点
1000~800K性价比最优
10000~1M+内存压力大

写入模式对比

模式吞吐适用场景
单行 INSERT极少量、临时数据
批量 INSERT通用
跨表批量 INSERT多设备汇总
SchemalessIoT 自动建模
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 语句显式更新。

参考

系统构架篇

数据模型

存储引擎

查询引擎

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TDengine (老段)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值