分类:10.SQL 参考 | 篇章:08 SQL 差异
> 适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-07-22
TDengine 兼容大部分标准 SQL 但有时序特性扩展和限制。本文系统列出与 MySQL/PostgreSQL 等关系数据库的核心差异,帮助迁移和误用排查。
核心差异概览
| 维度 | 标准 SQL | TDengine |
|---|---|---|
| 主键 | 任意类型 | 必须 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 写法
CREATE TABLE sensors (
id INT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(50),
ts DATETIME,
value DOUBLE,
INDEX idx_device (device_id)
);
INSERT INTO sensors VALUES (1, 'd001', '2026-06-04 12:00', 25.3);
-- TDengine 改写
CREATE STABLE sensors (
ts TIMESTAMP,
value DOUBLE
) TAGS (
device_id VARCHAR(50)
);
CREATE TABLE d001 USING sensors TAGS('d001');
INSERT INTO d001 VALUES ('2026-06-04 12:00:00', 25.3);
-- 或自动建表:
INSERT INTO d001 USING sensors TAGS('d001')
VALUES ('2026-06-04 12:00:00', 25.3);
查询改写
-- MySQL ROW_NUMBER
SELECT *, ROW_NUMBER() OVER (PARTITION BY device_id ORDER BY ts DESC) AS rn
FROM sensors WHERE rn = 1;
-- TDengine 改写:用 LAST_ROW
SELECT LAST_ROW(*) FROM sensors PARTITION BY tbname;
-- MySQL LAG
SELECT ts, value, LAG(value) OVER (PARTITION BY device_id ORDER BY ts) AS prev
FROM sensors;
-- TDengine 改写:用 DIFF
SELECT ts, value, value - DIFF(value) AS prev FROM sensors;
-- 或不直接计算 LAG,用 DIFF 表示变化
-- MySQL MERGE
MERGE INTO target USING source ON target.id = source.id
WHEN MATCHED THEN UPDATE SET val = source.val
WHEN NOT MATCHED THEN INSERT (id, val) VALUES (source.id, source.val);
-- TDengine 改写:
INSERT INTO target SELECT * FROM source;
-- ts 主键天然去重
窗口改写
-- 标准 OVER 窗口
SELECT id, ts,
AVG(val) OVER (ORDER BY ts ROWS BETWEEN 5 PRECEDING AND CURRENT ROW) AS rolling
FROM t;
-- TDengine MAVG
SELECT ts, MAVG(val, 6) AS rolling FROM t;
-- 标准 PARTITION BY ts BUCKET
SELECT TIMESTAMP_BUCKET(ts, INTERVAL '1 hour') AS h, AVG(val)
FROM t GROUP BY h;
-- TDengine INTERVAL
SELECT _wstart, AVG(val) FROM t INTERVAL(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 最佳实践》
预聚合
索引
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 提供实时分析、可视化、事件管理与报警等功能。
> 适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-07-22

322

被折叠的 条评论
为什么被折叠?



