TDengine SQL 与标准 SQL 差异 — 时序数据库的特殊性

TDengine SQL 与标准 SQL 差异 — 时序数据库的特殊性

分类:10.SQL 参考 |篇章:08 SQL 差异
>适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-07-22

点击了解免费详情

TDengine 兼容大部分标准 SQL 但有时序特性扩展和限制。本文系统列出与 MySQL/PostgreSQL 等关系数据库的核心差异,帮助迁移和误用排查。

核心差异概览

维度标准 SQLTDengine
主键任意类型必须 ts (TIMESTAMP)
表组织单层超级表/子表/普通表
JOIN任意条件必须含时间条件
窗口OVER 窗口INTERVAL/SESSION/STATE/EVENT/COUNT
存储行式列式
Schema严格支持 Schemaless
索引任意列时间+Tag 自动
事务ACID单语句原子

详细解析

1. 主键与数据模型

标准 SQL: CREATE TABLE t ( id INT PRIMARY KEY, name VARCHAR(100) ); TDengine: CREATE TABLE t ( ts TIMESTAMP, -- 必须是第一列 val FLOAT ); -- 时间列隐式为主键 超级表概念(无对应): TDengine 特有 一组同构子表的模板 Tag 作为标签维度

2. JOIN 限制

标准 SQL: SELECT * FROM t1 JOIN t2 ON t1.id = t2.id; -- 任意条件 OK TDengine: SELECT * FROM t1 JOIN t2 ON t1.ts = t2.ts AND t1.id = t2.id; -- 必须有时间相关条件 -- 替代方案: ASOF JOIN -- 时间近邻 WINDOW JOIN -- 时间窗口

3. 窗口函数

标准 SQL(OVER 窗口): SELECT id, val, AVG(val) OVER (PARTITION BY tag ORDER BY ts ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) FROM t; TDengine(窗口子句): SELECT _wstart, AVG(val) FROM t PARTITION BY tag INTERVAL(1h); -- 或 MAVG 函数 SELECT ts, MAVG(val, 5) FROM t; -- 不支持 OVER ... ROWS BETWEEN

4. DELETE/UPDATE

标准 SQL: DELETE FROM t WHERE id = 1; UPDATE t SET val = 0 WHERE id = 1; -- 无时间约束 TDengine: DELETE FROM t WHERE ts > T1 AND ts < T2; -- 必须有时间范围条件 UPDATE t SET val = 0 WHERE ts = '2026-06-04 12:00:00'; -- ts 是主键,唯一定位行 -- 不支持: WHERE val = 100 -- 必须含 ts

5. 索引

标准 SQL: CREATE INDEX idx ON t (name); CREATE INDEX idx ON t (name, age); -- 组合索引 TDengine: -- 数据列无显式索引 -- 块 SMA 自动统计 -- Tag 索引: CREATE INDEX idx ON super_table (tag_column); -- 不支持组合索引 -- 不支持函数索引

6. 事务与一致性

标准 SQL: BEGIN; INSERT INTO t1 ...; INSERT INTO t2 ...; COMMIT; -- ACID 事务 TDengine: -- 单语句原子(单 SQL 内全成或全败) INSERT INTO t1 ..., t2 ... ; -- 跨表批量也原子 -- 不支持: BEGIN/COMMIT/ROLLBACK 跨语句事务 -- 替代:业务层处理一致性

7. SELECT 限制

不支持/有限支持的特性: ① 复杂子查询: - 标量子查询有限 - 关联子查询不支持 ② OVER 窗口函数: - ROW_NUMBER/RANK/DENSE_RANK 不支持 - LAG/LEAD 不支持(用 DIFF/MAVG 替代) ③ WITH RECURSIVE: - 不支持递归 CTE ④ MERGE / UPSERT: - 不支持 MERGE INTO - INSERT 天然按 ts 去重 ⑤ FULL TEXT SEARCH: - 不内置全文检索

8. 数据类型差异

TDengine 特有: TIMESTAMP (主键) TDengine 缺少: TEXT (大文本) → 用 VARCHAR(N) BLOB (大二进制) → 用 VARBINARY(N) DATE / TIME (单独) → 都用 TIMESTAMP DECIMAL (精确小数) → 用 DOUBLE / 整数缩放 ENUM → 用 VARCHAR + 应用层约束 ARRAY → 用 JSON 或拆列 注意: VARCHAR 长度按字节计(N 字节) NCHAR 按字符计(N 个 Unicode 字符)

代码示例

迁移示例

-- MySQL 写法CREATETABLEsensors(idINTPRIMARYKEYAUTO_INCREMENT,device_idVARCHAR(50),tsDATETIME,valueDOUBLE,INDEXidx_device(device_id));INSERTINTOsensorsVALUES(1,'d001','2026-06-04 12:00',25.3);-- TDengine 改写CREATESTABLE sensors(tsTIMESTAMP,valueDOUBLE)TAGS(device_idVARCHAR(50));CREATETABLEd001USINGsensors TAGS('d001');INSERTINTOd001VALUES('2026-06-04 12:00:00',25.3);-- 或自动建表:INSERTINTOd001USINGsensors TAGS('d001')VALUES('2026-06-04 12:00:00',25.3);

查询改写

-- MySQL ROW_NUMBERSELECT*,ROW_NUMBER()OVER(PARTITIONBYdevice_idORDERBYtsDESC)ASrnFROMsensorsWHERErn=1;-- TDengine 改写:用 LAST_ROWSELECTLAST_ROW(*)FROMsensorsPARTITIONBYtbname;-- MySQL LAGSELECTts,value,LAG(value)OVER(PARTITIONBYdevice_idORDERBYts)ASprevFROMsensors;-- TDengine 改写:用 DIFFSELECTts,value,value-DIFF(value)ASprevFROMsensors;-- 或不直接计算 LAG,用 DIFF 表示变化-- MySQL MERGEMERGEINTOtargetUSINGsourceONtarget.id=source.idWHENMATCHEDTHENUPDATESETval=source.valWHENNOTMATCHEDTHENINSERT(id,val)VALUES(source.id,source.val);-- TDengine 改写:INSERTINTOtargetSELECT*FROMsource;-- ts 主键天然去重

窗口改写

-- 标准 OVER 窗口SELECTid,ts,AVG(val)OVER(ORDERBYtsROWSBETWEEN5PRECEDINGANDCURRENTROW)ASrollingFROMt;-- TDengine MAVGSELECTts,MAVG(val,6)ASrollingFROMt;-- 标准 PARTITION BY ts BUCKETSELECTTIMESTAMP_BUCKET(ts,INTERVAL'1 hour')ASh,AVG(val)FROMtGROUPBYh;-- TDengine INTERVALSELECT_wstart,AVG(val)FROMtINTERVAL(1h);

性能考量

迁移性能预期

场景TDengine vs MySQL/PostgreSQL
单设备写入10x~50x
批量写入100x+
时序聚合查询10x~100x
任意 JOIN受限(设计上不擅长)
全文检索不支持
复杂 OLAP部分支持

设计原则

关系数据库习惯TDengine 改写
自增 ID 主键时间戳 + Tag
单表千万行拆分为超级表 + 子表
任意 JOIN限制为时间相关
OVER 窗口时序窗口函数
事务业务层处理

FAQ

Q1: 标准 SQL 哪些功能不支持?

主要不支持:复杂 OVER 窗口、递归 CTE、跨语句事务、全文检索、复杂关联子查询。

Q2: 应用迁移成本大吗?

  • 时序场景:迁移简单(90% SQL 可用)
  • 复杂 OLTP:不适合,应保留原数据库

Q3: 能用 ORM 框架吗?

支持 JDBC/ODBC/Python DB-API 等标准接口,主流 ORM 大多兼容。某些 ORM 的高级特性(如懒加载、复杂查询构造)需注意。

Q4: 时区怎么处理?

存储 UTC,客户端按时区显示。建议明确指定时区。

Q5: 能与现有关系数据库共存吗?

可以。常见架构:

  • TDengine:时序数据
  • MySQL/Postgres:业务元数据
  • 应用层组合查询

参考

系统构架篇

  • 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 EXPLAIN 与查询优化》

数据写入

  • 01-《TDengine SQL INSERT》
  • 02-《TDengine 无模式写入》
  • 03-《TDengine STMT 写入》
  • 04-《TDengine 写入内部流程》
  • 05-《TDengine 数据更新删除》

数据订阅

  • 01-《TDengine 数据订阅》
  • 02-《TDengine 订阅 vs Kafka》
  • 03-《TDengine TMQ 消费流程》
  • 04-《TDengine 内部机制》
  • 05-《TDengine TMQ 最佳实践》

预聚合

  • 01-《TDengine RSMA》
  • 02-《TDengine TSMA — 时间维度的物化聚合视图》
  • 03-《TDengine SMA 内部实现》

索引

  • 01-《TDengine Tag 索引》
  • 02-《TDengine SMA 索引》

SQL 语句

  • 01-《TDengine DDL》
  • 02-《TDengine DML SELECT》
  • 03-《TDengine DML 函数完整参考》
  • 04-《TDengine JOIN 完整语法》
  • 05-《TDengine 窗口完整语法》
  • 06-《TDengine 操作符与表达式》
  • 07-《TDengine 系统表》

关于 TDengine

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