相较于其他众多时序数据库和实时数据库,TDengine的一个独特优势在于,自其首个版本发布之初便支持标准的SQL查询功能。这一特性极大地降低了用户在使用过程中的学习难度。本文将介绍如何在时序数据库中运用SQL查询来处理时序数据。
一、SQL查询的独特优势
1.1 低学习成本
对于熟悉关系型数据库的开发者来说,学习时序数据库的SQL查询几乎没有门槛。标准的SELECT语句、WHERE条件、ORDER BY排序等语法都可以直接使用。
1.2 生态兼容性
SQL作为最广泛使用的数据库查询语言,拥有丰富的工具生态:
- BI工具直接对接
- 各种ORM框架支持
- 成熟的查询优化器
1.3 TDengine的SQL特色
TDengine在标准SQL基础上,针对时序数据场景进行了扩展:
- 原生支持时间窗口查询
- 丰富的时序聚合函数
- 高效的时间范围过滤
二、基本查询语法
2.1 简单查询
最基础的查询是从表中检索所有数据:
SELECT * FROM meters;
2.2 条件过滤
通过WHERE语句指定条件,查询时序数据:
SELECT * FROM meters
WHERE voltage > 230
ORDER BY ts DESC
LIMIT 5;
上面的SQL从超级表meters中查询出电压voltage大于230V的记录,按时间降序排列,且仅输出前5行。
查询结果示例:
ts | current | voltage | phase | groupid | location |
===================================================================================================
2023-11-15 06:13:10.000 | 14.0601978 | 232 | 146.5000000 | 10 | California.Sunnyvale |
2023-11-15 06:13:10.000 | 14.0601978 | 232 | 146.5000000 | 1 | California.LosAngles |
2023-11-15 06:13:10.000 | 14.0601978 | 232 | 146.5000000 | 10 | California.Sunnyvale |
2023-11-15 06:13:10.000 | 14.0601978 | 232 | 146.5000000 | 5 | California.Cupertino |
2023-11-15 06:13:10.000 | 14.0601978 | 232 | 146.5000000 | 4 | California.SanFrancisco |
Query OK, 5 row(s) in set (0.145403s)
2.3 时间范围查询
时序数据查询中最常见的是按时间范围过滤:
SELECT * FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2023-01-01T00:00:00+08:00";
三、查询子句详解
3.1 SELECT子句
SELECT子句指定要查询的列:
-- 查询指定列
SELECT ts, current, voltage FROM meters;
-- 使用聚合函数
SELECT COUNT(*), AVG(voltage) FROM meters;
-- 使用表达式
SELECT ts, current * voltage AS power FROM meters;
3.2 WHERE子句
WHERE子句用于过滤数据,支持多种条件表达式:
-- 比较运算
SELECT * FROM meters WHERE voltage > 220;
-- 逻辑运算
SELECT * FROM meters WHERE voltage > 220 AND current > 10;
-- 时间范围
SELECT * FROM meters WHERE ts >= '2022-01-01 00:00:00' AND ts < '2022-02-01 00:00:00';
-- 标签过滤
SELECT * FROM meters WHERE location = 'California.SanFrancisco';
3.3 ORDER BY子句
ORDER BY子句用于对结果进行排序:
-- 按时间升序(默认)
SELECT * FROM meters ORDER BY ts ASC;
-- 按时间降序
SELECT * FROM meters ORDER BY ts DESC;
-- 多列排序
SELECT * FROM meters ORDER BY voltage DESC, ts ASC;
3.4 LIMIT和OFFSET
用于分页查询:
-- 返回前10条记录
SELECT * FROM meters LIMIT 10;
-- 跳过前10条,返回接下来的10条
SELECT * FROM meters LIMIT 10 OFFSET 10;
-- 简写形式
SELECT * FROM meters LIMIT 10, 10;
四、超级表查询
4.1 超级表查询特点
针对超级表的查询,TDengine将所有子表中的数据视为一个整体:
- 首先通过标签筛选出满足查询条件的表
- 然后在这些子表上分别查询时序数据
- 最终将各张子表的查询结果合并
4.2 超级表查询示例
SELECT groupid, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2023-01-01T00:00:00+08:00"
GROUP BY groupid;
查询结果:
groupid | avg(voltage) |
======================================
8 | 243.961981544901079 |
5 | 243.961981544901079 |
1 | 243.961981544901079 |
7 | 243.961981544901079 |
9 | 243.961981544901079 |
6 | 243.961981544901079 |
4 | 243.961981544901079 |
10 | 243.961981544901079 |
2 | 243.961981544901079 |
3 | 243.961981544901079 |
Query OK, 10 row(s) in set (0.042446s)
4.3 使用tbname伪列
在超级表查询中,可以使用tbname伪列来获取子表名称:
SELECT tbname, * FROM meters WHERE voltage > 230 LIMIT 5;
五、常用查询场景
5.1 最新数据查询
查询设备的最新数据:
SELECT * FROM d1001 ORDER BY ts DESC LIMIT 1;
5.2 时间段统计
查询某时间段内的统计数据:
SELECT COUNT(*) as cnt, AVG(current) as avg_current, MAX(voltage) as max_voltage
FROM meters
WHERE ts >= '2022-01-01 00:00:00' AND ts < '2022-01-02 00:00:00';
5.3 设备分组统计
按标签分组进行统计:
SELECT location, COUNT(*) as device_count, AVG(voltage) as avg_voltage
FROM meters
GROUP BY location;
5.4 异常数据查询
查询异常数据记录:
SELECT * FROM meters
WHERE voltage > 250 OR voltage < 180
ORDER BY ts DESC;
六、查询性能优化
6.1 时间范围优先
时序数据查询应优先使用时间范围条件,TDengine对时间范围查询有专门优化:
-- 推荐:包含时间范围
SELECT * FROM meters
WHERE ts >= '2022-01-01 00:00:00' AND ts < '2022-01-02 00:00:00'
AND voltage > 220;
-- 不推荐:只有非时间条件
SELECT * FROM meters WHERE voltage > 220;
6.2 合理使用LIMIT
对于大数据量的查询,使用LIMIT限制返回结果:
SELECT * FROM meters LIMIT 1000;
6.3 避免SELECT *
只查询需要的列,减少数据传输:
-- 推荐
SELECT ts, current, voltage FROM meters;
-- 不推荐
SELECT * FROM meters;
七、测试数据生成
为了更好地学习和测试查询功能,可以使用taosBenchmark工具生成测试数据:
taosBenchmark --start-timestamp=1600000000000 --tables=100 --records=10000000 --time-step=10000
上面的命令在TDengine中生成了一个用于测试的数据库,产生共10亿条时序数据:
- 时间戳从1600000000000(2020-09-13T20:26:40+08:00)开始
- 包含100个设备(子表)
- 每个设备有10000000条数据
- 时序数据的采集频率是10秒/条
总结
TDengine时序数据库的SQL查询功能为开发者提供了熟悉而强大的数据查询能力。通过标准SQL语法,开发者可以快速上手时序数据查询,无需学习新的查询语言。同时,TDengine针对时序数据场景进行了专门优化,在时间范围查询、聚合计算等方面表现出色。掌握这些基础查询技能,是构建工业数据管理平台(IDMP)和实时数据库应用的重要基础。TDengine凭借其SQL兼容性和高性能查询能力,成为物联网和工业场景的理想选择。

























